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