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 "../crypto/directory.h"
125#include "internal.h"
126
127
128static int xname_cmp(const X509_NAME **a, const X509_NAME **b) {
129  return X509_NAME_cmp(*a, *b);
130}
131
132/* TODO(davidben): Is there any reason this doesn't call
133 * |SSL_add_file_cert_subjects_to_stack|? */
134STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) {
135  BIO *in;
136  X509 *x = NULL;
137  X509_NAME *xn = NULL;
138  STACK_OF(X509_NAME) *ret = NULL, *sk;
139
140  sk = sk_X509_NAME_new(xname_cmp);
141  in = BIO_new(BIO_s_file());
142
143  if (sk == NULL || in == NULL) {
144    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
145    goto err;
146  }
147
148  if (!BIO_read_filename(in, file)) {
149    goto err;
150  }
151
152  for (;;) {
153    if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) {
154      break;
155    }
156    if (ret == NULL) {
157      ret = sk_X509_NAME_new_null();
158      if (ret == NULL) {
159        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
160        goto err;
161      }
162    }
163    xn = X509_get_subject_name(x);
164    if (xn == NULL) {
165      goto err;
166    }
167
168    /* check for duplicates */
169    xn = X509_NAME_dup(xn);
170    if (xn == NULL) {
171      goto err;
172    }
173    if (sk_X509_NAME_find(sk, NULL, xn)) {
174      X509_NAME_free(xn);
175    } else {
176      sk_X509_NAME_push(sk, xn);
177      sk_X509_NAME_push(ret, xn);
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 = 1;
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    xn = X509_NAME_dup(xn);
225    if (xn == NULL) {
226      goto err;
227    }
228    if (sk_X509_NAME_find(stack, NULL, xn)) {
229      X509_NAME_free(xn);
230    } else {
231      sk_X509_NAME_push(stack, xn);
232    }
233  }
234
235  ERR_clear_error();
236
237  if (0) {
238  err:
239    ret = 0;
240  }
241
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
250/* Add a directory of certs to a stack.
251 *
252 * \param stack the stack to append to.
253 * \param dir the directory to append from. All files in this directory will be
254 *     examined as potential certs. Any that are acceptable to
255 *     SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
256 *     be included.
257 * \return 1 for success, 0 for failure. Note that in the case of failure some
258 *     certs may have been added to \c stack. */
259int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
260                                       const char *dir) {
261  OPENSSL_DIR_CTX *d = NULL;
262  const char *filename;
263  int ret = 0;
264
265  /* Note that a side effect is that the CAs will be sorted by name */
266  while ((filename = OPENSSL_DIR_read(&d, dir))) {
267    char buf[1024];
268    int r;
269
270    if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
271      OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG);
272      goto err;
273    }
274
275    r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
276    if (r <= 0 || r >= (int)sizeof(buf) ||
277        !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
278      goto err;
279    }
280  }
281
282  if (errno) {
283    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
284    ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
285    goto err;
286  }
287
288  ret = 1;
289
290err:
291  if (d) {
292    OPENSSL_DIR_end(&d);
293  }
294  return ret;
295}
296
297int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
298  int reason_code;
299  BIO *in;
300  int ret = 0;
301  X509 *x = NULL;
302
303  in = BIO_new(BIO_s_file());
304  if (in == NULL) {
305    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
306    goto end;
307  }
308
309  if (BIO_read_filename(in, file) <= 0) {
310    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
311    goto end;
312  }
313
314  if (type == SSL_FILETYPE_ASN1) {
315    reason_code = ERR_R_ASN1_LIB;
316    x = d2i_X509_bio(in, NULL);
317  } else if (type == SSL_FILETYPE_PEM) {
318    reason_code = ERR_R_PEM_LIB;
319    x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
320                          ssl->ctx->default_passwd_callback_userdata);
321  } else {
322    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
323    goto end;
324  }
325
326  if (x == NULL) {
327    OPENSSL_PUT_ERROR(SSL, reason_code);
328    goto end;
329  }
330
331  ret = SSL_use_certificate(ssl, x);
332
333end:
334  X509_free(x);
335  BIO_free(in);
336
337  return ret;
338}
339
340int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
341  int reason_code, ret = 0;
342  BIO *in;
343  RSA *rsa = NULL;
344
345  in = BIO_new(BIO_s_file());
346  if (in == NULL) {
347    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
348    goto end;
349  }
350
351  if (BIO_read_filename(in, file) <= 0) {
352    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
353    goto end;
354  }
355
356  if (type == SSL_FILETYPE_ASN1) {
357    reason_code = ERR_R_ASN1_LIB;
358    rsa = d2i_RSAPrivateKey_bio(in, NULL);
359  } else if (type == SSL_FILETYPE_PEM) {
360    reason_code = ERR_R_PEM_LIB;
361    rsa =
362        PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
363                                   ssl->ctx->default_passwd_callback_userdata);
364  } else {
365    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
366    goto end;
367  }
368
369  if (rsa == NULL) {
370    OPENSSL_PUT_ERROR(SSL, reason_code);
371    goto end;
372  }
373  ret = SSL_use_RSAPrivateKey(ssl, rsa);
374  RSA_free(rsa);
375
376end:
377  BIO_free(in);
378  return ret;
379}
380
381int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
382  int reason_code, ret = 0;
383  BIO *in;
384  EVP_PKEY *pkey = NULL;
385
386  in = BIO_new(BIO_s_file());
387  if (in == NULL) {
388    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
389    goto end;
390  }
391
392  if (BIO_read_filename(in, file) <= 0) {
393    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
394    goto end;
395  }
396
397  if (type == SSL_FILETYPE_PEM) {
398    reason_code = ERR_R_PEM_LIB;
399    pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
400                                   ssl->ctx->default_passwd_callback_userdata);
401  } else if (type == SSL_FILETYPE_ASN1) {
402    reason_code = ERR_R_ASN1_LIB;
403    pkey = d2i_PrivateKey_bio(in, NULL);
404  } else {
405    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
406    goto end;
407  }
408
409  if (pkey == NULL) {
410    OPENSSL_PUT_ERROR(SSL, reason_code);
411    goto end;
412  }
413  ret = SSL_use_PrivateKey(ssl, pkey);
414  EVP_PKEY_free(pkey);
415
416end:
417  BIO_free(in);
418  return ret;
419}
420
421int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
422  int reason_code;
423  BIO *in;
424  int ret = 0;
425  X509 *x = NULL;
426
427  in = BIO_new(BIO_s_file());
428  if (in == NULL) {
429    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
430    goto end;
431  }
432
433  if (BIO_read_filename(in, file) <= 0) {
434    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
435    goto end;
436  }
437
438  if (type == SSL_FILETYPE_ASN1) {
439    reason_code = ERR_R_ASN1_LIB;
440    x = d2i_X509_bio(in, NULL);
441  } else if (type == SSL_FILETYPE_PEM) {
442    reason_code = ERR_R_PEM_LIB;
443    x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
444                          ctx->default_passwd_callback_userdata);
445  } else {
446    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
447    goto end;
448  }
449
450  if (x == NULL) {
451    OPENSSL_PUT_ERROR(SSL, reason_code);
452    goto end;
453  }
454
455  ret = SSL_CTX_use_certificate(ctx, x);
456
457end:
458  X509_free(x);
459  BIO_free(in);
460  return ret;
461}
462
463int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
464  int reason_code, ret = 0;
465  BIO *in;
466  RSA *rsa = NULL;
467
468  in = BIO_new(BIO_s_file());
469  if (in == NULL) {
470    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
471    goto end;
472  }
473
474  if (BIO_read_filename(in, file) <= 0) {
475    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
476    goto end;
477  }
478
479  if (type == SSL_FILETYPE_ASN1) {
480    reason_code = ERR_R_ASN1_LIB;
481    rsa = d2i_RSAPrivateKey_bio(in, NULL);
482  } else if (type == SSL_FILETYPE_PEM) {
483    reason_code = ERR_R_PEM_LIB;
484    rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
485                                     ctx->default_passwd_callback_userdata);
486  } else {
487    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
488    goto end;
489  }
490
491  if (rsa == NULL) {
492    OPENSSL_PUT_ERROR(SSL, reason_code);
493    goto end;
494  }
495  ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
496  RSA_free(rsa);
497
498end:
499  BIO_free(in);
500  return ret;
501}
502
503int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
504  int reason_code, ret = 0;
505  BIO *in;
506  EVP_PKEY *pkey = NULL;
507
508  in = BIO_new(BIO_s_file());
509  if (in == NULL) {
510    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
511    goto end;
512  }
513
514  if (BIO_read_filename(in, file) <= 0) {
515    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
516    goto end;
517  }
518
519  if (type == SSL_FILETYPE_PEM) {
520    reason_code = ERR_R_PEM_LIB;
521    pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback,
522                                   ctx->default_passwd_callback_userdata);
523  } else if (type == SSL_FILETYPE_ASN1) {
524    reason_code = ERR_R_ASN1_LIB;
525    pkey = d2i_PrivateKey_bio(in, NULL);
526  } else {
527    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
528    goto end;
529  }
530
531  if (pkey == NULL) {
532    OPENSSL_PUT_ERROR(SSL, reason_code);
533    goto end;
534  }
535  ret = SSL_CTX_use_PrivateKey(ctx, pkey);
536  EVP_PKEY_free(pkey);
537
538end:
539  BIO_free(in);
540  return ret;
541}
542
543/* Read a file that contains our certificate in "PEM" format, possibly followed
544 * by a sequence of CA certificates that should be sent to the peer in the
545 * Certificate message. */
546int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
547  BIO *in;
548  int ret = 0;
549  X509 *x = NULL;
550
551  ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
552
553  in = BIO_new(BIO_s_file());
554  if (in == NULL) {
555    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
556    goto end;
557  }
558
559  if (BIO_read_filename(in, file) <= 0) {
560    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
561    goto end;
562  }
563
564  x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
565                            ctx->default_passwd_callback_userdata);
566  if (x == NULL) {
567    OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
568    goto end;
569  }
570
571  ret = SSL_CTX_use_certificate(ctx, x);
572
573  if (ERR_peek_error() != 0) {
574    ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
575  }
576
577  if (ret) {
578    /* If we could set up our certificate, now proceed to the CA
579     * certificates. */
580    X509 *ca;
581    int r;
582    uint32_t err;
583
584    SSL_CTX_clear_chain_certs(ctx);
585
586    while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
587                                   ctx->default_passwd_callback_userdata)) !=
588           NULL) {
589      r = SSL_CTX_add0_chain_cert(ctx, ca);
590      if (!r) {
591        X509_free(ca);
592        ret = 0;
593        goto end;
594      }
595      /* Note that we must not free r if it was successfully added to the chain
596       * (while we must free the main certificate, since its reference count is
597       * increased by SSL_CTX_use_certificate). */
598    }
599
600    /* When the while loop ends, it's usually just EOF. */
601    err = ERR_peek_last_error();
602    if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
603        ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
604      ERR_clear_error();
605    } else {
606      ret = 0; /* some real error */
607    }
608  }
609
610end:
611  X509_free(x);
612  BIO_free(in);
613  return ret;
614}
615
616void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
617  ctx->default_passwd_callback = cb;
618}
619
620void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
621  ctx->default_passwd_callback_userdata = data;
622}
623
624SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
625  return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio,
626                         out);
627}
628
629int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
630  return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
631}
632
633IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
634