1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to.  The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 *    notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 *    notice, this list of conditions and the following disclaimer in the
29 *    documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 *    must display the following acknowledgement:
32 *    "This product includes cryptographic software written by
33 *     Eric Young (eay@cryptsoft.com)"
34 *    The word 'cryptographic' can be left out if the rouines from the library
35 *    being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 *    the apps directory (application code) you must include an acknowledgement:
38 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed.  i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
65 *    notice, this list of conditions and the following disclaimer.
66 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 *    notice, this list of conditions and the following disclaimer in
69 *    the documentation and/or other materials provided with the
70 *    distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 *    software must display the following acknowledgment:
74 *    "This product includes software developed by the OpenSSL Project
75 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 *    endorse or promote products derived from this software without
79 *    prior written permission. For written permission, please contact
80 *    openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 *    nor may "OpenSSL" appear in their names without prior written
84 *    permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 *    acknowledgment:
88 *    "This product includes software developed by the OpenSSL Project
89 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com).  This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com).
108 *
109 */
110
111#include <openssl/ssl.h>
112
113#include <errno.h>
114#include <string.h>
115
116#include <openssl/asn1.h>
117#include <openssl/bio.h>
118#include <openssl/err.h>
119#include <openssl/mem.h>
120#include <openssl/pem.h>
121#include <openssl/stack.h>
122#include <openssl/x509.h>
123
124#include "internal.h"
125
126
127static int xname_cmp(const X509_NAME **a, const X509_NAME **b) {
128  return X509_NAME_cmp(*a, *b);
129}
130
131// TODO(davidben): Is there any reason this doesn't call
132// |SSL_add_file_cert_subjects_to_stack|?
133STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) {
134  BIO *in;
135  X509 *x = NULL;
136  X509_NAME *xn = NULL;
137  STACK_OF(X509_NAME) *ret = NULL, *sk;
138
139  sk = sk_X509_NAME_new(xname_cmp);
140  in = BIO_new(BIO_s_file());
141
142  if (sk == NULL || in == NULL) {
143    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
144    goto err;
145  }
146
147  if (!BIO_read_filename(in, file)) {
148    goto err;
149  }
150
151  for (;;) {
152    if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) {
153      break;
154    }
155    if (ret == NULL) {
156      ret = sk_X509_NAME_new_null();
157      if (ret == NULL) {
158        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
159        goto err;
160      }
161    }
162    xn = X509_get_subject_name(x);
163    if (xn == NULL) {
164      goto err;
165    }
166
167    // Check for duplicates.
168    if (sk_X509_NAME_find(sk, NULL, xn)) {
169      continue;
170    }
171
172    xn = X509_NAME_dup(xn);
173    if (xn == NULL ||
174        !sk_X509_NAME_push(sk /* non-owning */, xn) ||
175        !sk_X509_NAME_push(ret /* owning */, xn)) {
176      X509_NAME_free(xn);
177      goto err;
178    }
179  }
180
181  if (0) {
182  err:
183    sk_X509_NAME_pop_free(ret, X509_NAME_free);
184    ret = NULL;
185  }
186
187  sk_X509_NAME_free(sk);
188  BIO_free(in);
189  X509_free(x);
190  if (ret != NULL) {
191    ERR_clear_error();
192  }
193  return ret;
194}
195
196int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
197                                        const char *file) {
198  BIO *in;
199  X509 *x = NULL;
200  X509_NAME *xn = NULL;
201  int ret = 0;
202  int (*oldcmp)(const X509_NAME **a, const X509_NAME **b);
203
204  oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
205  in = BIO_new(BIO_s_file());
206
207  if (in == NULL) {
208    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
209    goto err;
210  }
211
212  if (!BIO_read_filename(in, file)) {
213    goto err;
214  }
215
216  for (;;) {
217    if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) {
218      break;
219    }
220    xn = X509_get_subject_name(x);
221    if (xn == NULL) {
222      goto err;
223    }
224
225    // Check for duplicates.
226    if (sk_X509_NAME_find(stack, NULL, xn)) {
227      continue;
228    }
229
230    xn = X509_NAME_dup(xn);
231    if (xn == NULL ||
232        !sk_X509_NAME_push(stack, xn)) {
233      X509_NAME_free(xn);
234      goto err;
235    }
236  }
237
238  ERR_clear_error();
239  ret = 1;
240
241err:
242  BIO_free(in);
243  X509_free(x);
244
245  (void) sk_X509_NAME_set_cmp_func(stack, oldcmp);
246
247  return ret;
248}
249
250int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
251  int reason_code;
252  BIO *in;
253  int ret = 0;
254  X509 *x = NULL;
255
256  in = BIO_new(BIO_s_file());
257  if (in == NULL) {
258    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
259    goto end;
260  }
261
262  if (BIO_read_filename(in, file) <= 0) {
263    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
264    goto end;
265  }
266
267  if (type == SSL_FILETYPE_ASN1) {
268    reason_code = ERR_R_ASN1_LIB;
269    x = d2i_X509_bio(in, NULL);
270  } else if (type == SSL_FILETYPE_PEM) {
271    reason_code = ERR_R_PEM_LIB;
272    x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
273                          ssl->ctx->default_passwd_callback_userdata);
274  } else {
275    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
276    goto end;
277  }
278
279  if (x == NULL) {
280    OPENSSL_PUT_ERROR(SSL, reason_code);
281    goto end;
282  }
283
284  ret = SSL_use_certificate(ssl, x);
285
286end:
287  X509_free(x);
288  BIO_free(in);
289
290  return ret;
291}
292
293int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
294  int reason_code, ret = 0;
295  BIO *in;
296  RSA *rsa = NULL;
297
298  in = BIO_new(BIO_s_file());
299  if (in == NULL) {
300    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
301    goto end;
302  }
303
304  if (BIO_read_filename(in, file) <= 0) {
305    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
306    goto end;
307  }
308
309  if (type == SSL_FILETYPE_ASN1) {
310    reason_code = ERR_R_ASN1_LIB;
311    rsa = d2i_RSAPrivateKey_bio(in, NULL);
312  } else if (type == SSL_FILETYPE_PEM) {
313    reason_code = ERR_R_PEM_LIB;
314    rsa =
315        PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
316                                   ssl->ctx->default_passwd_callback_userdata);
317  } else {
318    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
319    goto end;
320  }
321
322  if (rsa == NULL) {
323    OPENSSL_PUT_ERROR(SSL, reason_code);
324    goto end;
325  }
326  ret = SSL_use_RSAPrivateKey(ssl, rsa);
327  RSA_free(rsa);
328
329end:
330  BIO_free(in);
331  return ret;
332}
333
334int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
335  int reason_code, ret = 0;
336  BIO *in;
337  EVP_PKEY *pkey = NULL;
338
339  in = BIO_new(BIO_s_file());
340  if (in == NULL) {
341    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
342    goto end;
343  }
344
345  if (BIO_read_filename(in, file) <= 0) {
346    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
347    goto end;
348  }
349
350  if (type == SSL_FILETYPE_PEM) {
351    reason_code = ERR_R_PEM_LIB;
352    pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
353                                   ssl->ctx->default_passwd_callback_userdata);
354  } else if (type == SSL_FILETYPE_ASN1) {
355    reason_code = ERR_R_ASN1_LIB;
356    pkey = d2i_PrivateKey_bio(in, NULL);
357  } else {
358    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
359    goto end;
360  }
361
362  if (pkey == NULL) {
363    OPENSSL_PUT_ERROR(SSL, reason_code);
364    goto end;
365  }
366  ret = SSL_use_PrivateKey(ssl, pkey);
367  EVP_PKEY_free(pkey);
368
369end:
370  BIO_free(in);
371  return ret;
372}
373
374int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
375  int reason_code;
376  BIO *in;
377  int ret = 0;
378  X509 *x = NULL;
379
380  in = BIO_new(BIO_s_file());
381  if (in == NULL) {
382    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
383    goto end;
384  }
385
386  if (BIO_read_filename(in, file) <= 0) {
387    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
388    goto end;
389  }
390
391  if (type == SSL_FILETYPE_ASN1) {
392    reason_code = ERR_R_ASN1_LIB;
393    x = d2i_X509_bio(in, NULL);
394  } else if (type == SSL_FILETYPE_PEM) {
395    reason_code = ERR_R_PEM_LIB;
396    x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
397                          ctx->default_passwd_callback_userdata);
398  } else {
399    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
400    goto end;
401  }
402
403  if (x == NULL) {
404    OPENSSL_PUT_ERROR(SSL, reason_code);
405    goto end;
406  }
407
408  ret = SSL_CTX_use_certificate(ctx, x);
409
410end:
411  X509_free(x);
412  BIO_free(in);
413  return ret;
414}
415
416int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
417  int reason_code, ret = 0;
418  BIO *in;
419  RSA *rsa = NULL;
420
421  in = BIO_new(BIO_s_file());
422  if (in == NULL) {
423    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
424    goto end;
425  }
426
427  if (BIO_read_filename(in, file) <= 0) {
428    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
429    goto end;
430  }
431
432  if (type == SSL_FILETYPE_ASN1) {
433    reason_code = ERR_R_ASN1_LIB;
434    rsa = d2i_RSAPrivateKey_bio(in, NULL);
435  } else if (type == SSL_FILETYPE_PEM) {
436    reason_code = ERR_R_PEM_LIB;
437    rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
438                                     ctx->default_passwd_callback_userdata);
439  } else {
440    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
441    goto end;
442  }
443
444  if (rsa == NULL) {
445    OPENSSL_PUT_ERROR(SSL, reason_code);
446    goto end;
447  }
448  ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
449  RSA_free(rsa);
450
451end:
452  BIO_free(in);
453  return ret;
454}
455
456int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
457  int reason_code, ret = 0;
458  BIO *in;
459  EVP_PKEY *pkey = NULL;
460
461  in = BIO_new(BIO_s_file());
462  if (in == NULL) {
463    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
464    goto end;
465  }
466
467  if (BIO_read_filename(in, file) <= 0) {
468    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
469    goto end;
470  }
471
472  if (type == SSL_FILETYPE_PEM) {
473    reason_code = ERR_R_PEM_LIB;
474    pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback,
475                                   ctx->default_passwd_callback_userdata);
476  } else if (type == SSL_FILETYPE_ASN1) {
477    reason_code = ERR_R_ASN1_LIB;
478    pkey = d2i_PrivateKey_bio(in, NULL);
479  } else {
480    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
481    goto end;
482  }
483
484  if (pkey == NULL) {
485    OPENSSL_PUT_ERROR(SSL, reason_code);
486    goto end;
487  }
488  ret = SSL_CTX_use_PrivateKey(ctx, pkey);
489  EVP_PKEY_free(pkey);
490
491end:
492  BIO_free(in);
493  return ret;
494}
495
496// Read a file that contains our certificate in "PEM" format, possibly followed
497// by a sequence of CA certificates that should be sent to the peer in the
498// Certificate message.
499int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
500  BIO *in;
501  int ret = 0;
502  X509 *x = NULL;
503
504  ERR_clear_error();  // clear error stack for SSL_CTX_use_certificate()
505
506  in = BIO_new(BIO_s_file());
507  if (in == NULL) {
508    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
509    goto end;
510  }
511
512  if (BIO_read_filename(in, file) <= 0) {
513    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
514    goto end;
515  }
516
517  x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
518                            ctx->default_passwd_callback_userdata);
519  if (x == NULL) {
520    OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
521    goto end;
522  }
523
524  ret = SSL_CTX_use_certificate(ctx, x);
525
526  if (ERR_peek_error() != 0) {
527    ret = 0;  // Key/certificate mismatch doesn't imply ret==0 ...
528  }
529
530  if (ret) {
531    // If we could set up our certificate, now proceed to the CA
532    // certificates.
533    X509 *ca;
534    int r;
535    uint32_t err;
536
537    SSL_CTX_clear_chain_certs(ctx);
538
539    while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
540                                   ctx->default_passwd_callback_userdata)) !=
541           NULL) {
542      r = SSL_CTX_add0_chain_cert(ctx, ca);
543      if (!r) {
544        X509_free(ca);
545        ret = 0;
546        goto end;
547      }
548      // Note that we must not free r if it was successfully added to the chain
549      // (while we must free the main certificate, since its reference count is
550      // increased by SSL_CTX_use_certificate).
551    }
552
553    // When the while loop ends, it's usually just EOF.
554    err = ERR_peek_last_error();
555    if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
556        ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
557      ERR_clear_error();
558    } else {
559      ret = 0;  // some real error
560    }
561  }
562
563end:
564  X509_free(x);
565  BIO_free(in);
566  return ret;
567}
568
569void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
570  ctx->default_passwd_callback = cb;
571}
572
573pem_password_cb *SSL_CTX_get_default_passwd_cb(const SSL_CTX *ctx) {
574  return ctx->default_passwd_callback;
575}
576
577void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
578  ctx->default_passwd_callback_userdata = data;
579}
580
581void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx) {
582  return ctx->default_passwd_callback_userdata;
583}
584