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
xname_cmp(const X509_NAME ** a,const X509_NAME ** b)127 static 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|?
STACK_OF(X509_NAME)133 STACK_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
SSL_add_file_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * file)196 int 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
241 err:
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
SSL_use_certificate_file(SSL * ssl,const char * file,int type)250 int 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
286 end:
287 X509_free(x);
288 BIO_free(in);
289
290 return ret;
291 }
292
SSL_use_RSAPrivateKey_file(SSL * ssl,const char * file,int type)293 int 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
329 end:
330 BIO_free(in);
331 return ret;
332 }
333
SSL_use_PrivateKey_file(SSL * ssl,const char * file,int type)334 int 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
369 end:
370 BIO_free(in);
371 return ret;
372 }
373
SSL_CTX_use_certificate_file(SSL_CTX * ctx,const char * file,int type)374 int 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
410 end:
411 X509_free(x);
412 BIO_free(in);
413 return ret;
414 }
415
SSL_CTX_use_RSAPrivateKey_file(SSL_CTX * ctx,const char * file,int type)416 int 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
451 end:
452 BIO_free(in);
453 return ret;
454 }
455
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)456 int 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
491 end:
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.
SSL_CTX_use_certificate_chain_file(SSL_CTX * ctx,const char * file)499 int 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
563 end:
564 X509_free(x);
565 BIO_free(in);
566 return ret;
567 }
568
SSL_CTX_set_default_passwd_cb(SSL_CTX * ctx,pem_password_cb * cb)569 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
570 ctx->default_passwd_callback = cb;
571 }
572
SSL_CTX_get_default_passwd_cb(const SSL_CTX * ctx)573 pem_password_cb *SSL_CTX_get_default_passwd_cb(const SSL_CTX *ctx) {
574 return ctx->default_passwd_callback;
575 }
576
SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX * ctx,void * data)577 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
578 ctx->default_passwd_callback_userdata = data;
579 }
580
SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX * ctx)581 void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx) {
582 return ctx->default_passwd_callback_userdata;
583 }
584