1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 107 * Hudson (tjh (at) 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 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|? 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 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 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 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 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 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 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 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. 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 569 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { 570 ctx->default_passwd_callback = cb; 571 } 572 573 pem_password_cb *SSL_CTX_get_default_passwd_cb(const SSL_CTX *ctx) { 574 return ctx->default_passwd_callback; 575 } 576 577 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) { 578 ctx->default_passwd_callback_userdata = data; 579 } 580 581 void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx) { 582 return ctx->default_passwd_callback_userdata; 583 } 584