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