blob: 748d50cac9446fb1481a14f1678199d890f21f66 [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
David Benjamin72279902015-10-17 22:15:37 -0400116#include <openssl/asn1.h>
David Benjamin443a1f62015-09-04 15:05:05 -0400117#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
David Benjamin443a1f62015-09-04 15:05:05 -0400124#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
David Benjamin59937042015-09-19 13:04:22 -0400131/* TODO(davidben): Is there any reason this doesn't call
132 * |SSL_add_file_cert_subjects_to_stack|? */
David Benjamin443a1f62015-09-04 15:05:05 -0400133STACK_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 xn = X509_NAME_dup(xn);
169 if (xn == NULL) {
170 goto err;
171 }
172 if (sk_X509_NAME_find(sk, NULL, xn)) {
173 X509_NAME_free(xn);
174 } else {
175 sk_X509_NAME_push(sk, xn);
176 sk_X509_NAME_push(ret, xn);
177 }
178 }
179
180 if (0) {
181 err:
182 sk_X509_NAME_pop_free(ret, X509_NAME_free);
183 ret = NULL;
184 }
185
186 sk_X509_NAME_free(sk);
187 BIO_free(in);
188 X509_free(x);
189 if (ret != NULL) {
190 ERR_clear_error();
191 }
192 return ret;
193}
194
David Benjamin443a1f62015-09-04 15:05:05 -0400195int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
196 const char *file) {
197 BIO *in;
198 X509 *x = NULL;
199 X509_NAME *xn = NULL;
200 int ret = 1;
201 int (*oldcmp)(const X509_NAME **a, const X509_NAME **b);
202
203 oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
204 in = BIO_new(BIO_s_file());
205
206 if (in == NULL) {
207 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
208 goto err;
209 }
210
211 if (!BIO_read_filename(in, file)) {
212 goto err;
213 }
214
215 for (;;) {
216 if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) {
217 break;
218 }
219 xn = X509_get_subject_name(x);
220 if (xn == NULL) {
221 goto err;
222 }
223 xn = X509_NAME_dup(xn);
224 if (xn == NULL) {
225 goto err;
226 }
227 if (sk_X509_NAME_find(stack, NULL, xn)) {
228 X509_NAME_free(xn);
229 } else {
230 sk_X509_NAME_push(stack, xn);
231 }
232 }
233
234 ERR_clear_error();
235
236 if (0) {
237 err:
238 ret = 0;
239 }
240
241 BIO_free(in);
242 X509_free(x);
243
244 (void) sk_X509_NAME_set_cmp_func(stack, oldcmp);
245
246 return ret;
247}
248
David Benjamin443a1f62015-09-04 15:05:05 -0400249int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
250 int reason_code;
251 BIO *in;
252 int ret = 0;
253 X509 *x = NULL;
254
255 in = BIO_new(BIO_s_file());
256 if (in == NULL) {
257 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
258 goto end;
259 }
260
261 if (BIO_read_filename(in, file) <= 0) {
262 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
263 goto end;
264 }
265
266 if (type == SSL_FILETYPE_ASN1) {
267 reason_code = ERR_R_ASN1_LIB;
268 x = d2i_X509_bio(in, NULL);
269 } else if (type == SSL_FILETYPE_PEM) {
270 reason_code = ERR_R_PEM_LIB;
271 x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
272 ssl->ctx->default_passwd_callback_userdata);
273 } else {
274 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
275 goto end;
276 }
277
278 if (x == NULL) {
279 OPENSSL_PUT_ERROR(SSL, reason_code);
280 goto end;
281 }
282
283 ret = SSL_use_certificate(ssl, x);
284
285end:
286 X509_free(x);
287 BIO_free(in);
288
289 return ret;
290}
291
292int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
293 int reason_code, ret = 0;
294 BIO *in;
295 RSA *rsa = NULL;
296
297 in = BIO_new(BIO_s_file());
298 if (in == NULL) {
299 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
300 goto end;
301 }
302
303 if (BIO_read_filename(in, file) <= 0) {
304 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
305 goto end;
306 }
307
308 if (type == SSL_FILETYPE_ASN1) {
309 reason_code = ERR_R_ASN1_LIB;
310 rsa = d2i_RSAPrivateKey_bio(in, NULL);
311 } else if (type == SSL_FILETYPE_PEM) {
312 reason_code = ERR_R_PEM_LIB;
313 rsa =
314 PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
315 ssl->ctx->default_passwd_callback_userdata);
316 } else {
317 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
318 goto end;
319 }
320
321 if (rsa == NULL) {
322 OPENSSL_PUT_ERROR(SSL, reason_code);
323 goto end;
324 }
325 ret = SSL_use_RSAPrivateKey(ssl, rsa);
326 RSA_free(rsa);
327
328end:
329 BIO_free(in);
330 return ret;
331}
332
333int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
334 int reason_code, ret = 0;
335 BIO *in;
336 EVP_PKEY *pkey = NULL;
337
338 in = BIO_new(BIO_s_file());
339 if (in == NULL) {
340 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
341 goto end;
342 }
343
344 if (BIO_read_filename(in, file) <= 0) {
345 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
346 goto end;
347 }
348
349 if (type == SSL_FILETYPE_PEM) {
350 reason_code = ERR_R_PEM_LIB;
351 pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
352 ssl->ctx->default_passwd_callback_userdata);
353 } else if (type == SSL_FILETYPE_ASN1) {
354 reason_code = ERR_R_ASN1_LIB;
355 pkey = d2i_PrivateKey_bio(in, NULL);
356 } else {
357 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
358 goto end;
359 }
360
361 if (pkey == NULL) {
362 OPENSSL_PUT_ERROR(SSL, reason_code);
363 goto end;
364 }
365 ret = SSL_use_PrivateKey(ssl, pkey);
366 EVP_PKEY_free(pkey);
367
368end:
369 BIO_free(in);
370 return ret;
371}
372
373int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
374 int reason_code;
375 BIO *in;
376 int ret = 0;
377 X509 *x = NULL;
378
379 in = BIO_new(BIO_s_file());
380 if (in == NULL) {
381 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
382 goto end;
383 }
384
385 if (BIO_read_filename(in, file) <= 0) {
386 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
387 goto end;
388 }
389
390 if (type == SSL_FILETYPE_ASN1) {
391 reason_code = ERR_R_ASN1_LIB;
392 x = d2i_X509_bio(in, NULL);
393 } else if (type == SSL_FILETYPE_PEM) {
394 reason_code = ERR_R_PEM_LIB;
395 x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
396 ctx->default_passwd_callback_userdata);
397 } else {
398 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
399 goto end;
400 }
401
402 if (x == NULL) {
403 OPENSSL_PUT_ERROR(SSL, reason_code);
404 goto end;
405 }
406
407 ret = SSL_CTX_use_certificate(ctx, x);
408
409end:
410 X509_free(x);
411 BIO_free(in);
412 return ret;
413}
414
415int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
416 int reason_code, ret = 0;
417 BIO *in;
418 RSA *rsa = NULL;
419
420 in = BIO_new(BIO_s_file());
421 if (in == NULL) {
422 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
423 goto end;
424 }
425
426 if (BIO_read_filename(in, file) <= 0) {
427 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
428 goto end;
429 }
430
431 if (type == SSL_FILETYPE_ASN1) {
432 reason_code = ERR_R_ASN1_LIB;
433 rsa = d2i_RSAPrivateKey_bio(in, NULL);
434 } else if (type == SSL_FILETYPE_PEM) {
435 reason_code = ERR_R_PEM_LIB;
436 rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
437 ctx->default_passwd_callback_userdata);
438 } else {
439 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
440 goto end;
441 }
442
443 if (rsa == NULL) {
444 OPENSSL_PUT_ERROR(SSL, reason_code);
445 goto end;
446 }
447 ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
448 RSA_free(rsa);
449
450end:
451 BIO_free(in);
452 return ret;
453}
454
455int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
456 int reason_code, ret = 0;
457 BIO *in;
458 EVP_PKEY *pkey = NULL;
459
460 in = BIO_new(BIO_s_file());
461 if (in == NULL) {
462 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
463 goto end;
464 }
465
466 if (BIO_read_filename(in, file) <= 0) {
467 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
468 goto end;
469 }
470
471 if (type == SSL_FILETYPE_PEM) {
472 reason_code = ERR_R_PEM_LIB;
473 pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback,
474 ctx->default_passwd_callback_userdata);
475 } else if (type == SSL_FILETYPE_ASN1) {
476 reason_code = ERR_R_ASN1_LIB;
477 pkey = d2i_PrivateKey_bio(in, NULL);
478 } else {
479 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
480 goto end;
481 }
482
483 if (pkey == NULL) {
484 OPENSSL_PUT_ERROR(SSL, reason_code);
485 goto end;
486 }
487 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
488 EVP_PKEY_free(pkey);
489
490end:
491 BIO_free(in);
492 return ret;
493}
494
495/* Read a file that contains our certificate in "PEM" format, possibly followed
496 * by a sequence of CA certificates that should be sent to the peer in the
497 * Certificate message. */
498int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
499 BIO *in;
500 int ret = 0;
501 X509 *x = NULL;
502
503 ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
504
505 in = BIO_new(BIO_s_file());
506 if (in == NULL) {
507 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
508 goto end;
509 }
510
511 if (BIO_read_filename(in, file) <= 0) {
512 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
513 goto end;
514 }
515
516 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
517 ctx->default_passwd_callback_userdata);
518 if (x == NULL) {
519 OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
520 goto end;
521 }
522
523 ret = SSL_CTX_use_certificate(ctx, x);
524
525 if (ERR_peek_error() != 0) {
526 ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
527 }
528
529 if (ret) {
530 /* If we could set up our certificate, now proceed to the CA
531 * certificates. */
532 X509 *ca;
533 int r;
534 uint32_t err;
535
536 SSL_CTX_clear_chain_certs(ctx);
537
538 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
539 ctx->default_passwd_callback_userdata)) !=
540 NULL) {
541 r = SSL_CTX_add0_chain_cert(ctx, ca);
542 if (!r) {
543 X509_free(ca);
544 ret = 0;
545 goto end;
546 }
547 /* Note that we must not free r if it was successfully added to the chain
548 * (while we must free the main certificate, since its reference count is
549 * increased by SSL_CTX_use_certificate). */
550 }
551
552 /* When the while loop ends, it's usually just EOF. */
553 err = ERR_peek_last_error();
554 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
555 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
556 ERR_clear_error();
557 } else {
558 ret = 0; /* some real error */
559 }
560 }
561
562end:
563 X509_free(x);
564 BIO_free(in);
565 return ret;
566}
567
David Benjamin42fea372015-09-19 01:22:44 -0400568void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
569 ctx->default_passwd_callback = cb;
570}
571
572void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
573 ctx->default_passwd_callback_userdata = data;
574}
575
David Benjamin72279902015-10-17 22:15:37 -0400576SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
577 return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio,
578 out);
579}
580
581int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
582 return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
583}
584
David Benjamin443a1f62015-09-04 15:05:05 -0400585IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)