blob: 45c989165d529145c64408689f2a02f4d9daf60d [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* 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#include <stdio.h>
58
59#include <openssl/bio.h>
60#include <openssl/err.h>
61#include <openssl/evp.h>
62#include <openssl/mem.h>
63#include <openssl/obj.h>
64#include <openssl/pem.h>
65#include <openssl/x509.h>
66
David Benjamin2ee94aa2015-04-07 22:38:30 -040067#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070068
69static int ssl_set_cert(CERT *c, X509 *x509);
70static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
Adam Langley95c29f32014-06-20 12:00:00 -070071
Adam Langleyfcf25832014-12-18 17:42:32 -080072int SSL_use_certificate(SSL *ssl, X509 *x) {
73 if (x == NULL) {
74 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER);
75 return 0;
76 }
Adam Langleyfcf25832014-12-18 17:42:32 -080077 return ssl_set_cert(ssl->cert, x);
78}
Adam Langley95c29f32014-06-20 12:00:00 -070079
Adam Langleyfcf25832014-12-18 17:42:32 -080080int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
81 int reason_code;
82 BIO *in;
83 int ret = 0;
84 X509 *x = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -070085
Adam Langleyfcf25832014-12-18 17:42:32 -080086 in = BIO_new(BIO_s_file());
87 if (in == NULL) {
88 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_BUF_LIB);
89 goto end;
90 }
Adam Langley95c29f32014-06-20 12:00:00 -070091
Adam Langleyfcf25832014-12-18 17:42:32 -080092 if (BIO_read_filename(in, file) <= 0) {
93 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_SYS_LIB);
94 goto end;
95 }
Adam Langley95c29f32014-06-20 12:00:00 -070096
Adam Langleyfcf25832014-12-18 17:42:32 -080097 if (type == SSL_FILETYPE_ASN1) {
98 reason_code = ERR_R_ASN1_LIB;
99 x = d2i_X509_bio(in, NULL);
100 } else if (type == SSL_FILETYPE_PEM) {
101 reason_code = ERR_R_PEM_LIB;
102 x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
103 ssl->ctx->default_passwd_callback_userdata);
104 } else {
105 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, SSL_R_BAD_SSL_FILETYPE);
106 goto end;
107 }
Adam Langley95c29f32014-06-20 12:00:00 -0700108
Adam Langleyfcf25832014-12-18 17:42:32 -0800109 if (x == NULL) {
110 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, reason_code);
111 goto end;
112 }
Adam Langley95c29f32014-06-20 12:00:00 -0700113
Adam Langleyfcf25832014-12-18 17:42:32 -0800114 ret = SSL_use_certificate(ssl, x);
Adam Langley95c29f32014-06-20 12:00:00 -0700115
116end:
Adam Langleyfcf25832014-12-18 17:42:32 -0800117 if (x != NULL) {
118 X509_free(x);
119 }
120 if (in != NULL) {
121 BIO_free(in);
122 }
123
124 return ret;
125}
126
127int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) {
128 X509 *x;
129 int ret;
130
131 x = d2i_X509(NULL, &d, (long)len);
132 if (x == NULL) {
133 OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_ASN1, ERR_R_ASN1_LIB);
134 return 0;
135 }
136
137 ret = SSL_use_certificate(ssl, x);
138 X509_free(x);
139 return ret;
140}
141
142int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
143 EVP_PKEY *pkey;
144 int ret;
145
146 if (rsa == NULL) {
147 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER);
148 return 0;
149 }
150
Adam Langleyfcf25832014-12-18 17:42:32 -0800151 pkey = EVP_PKEY_new();
152 if (pkey == NULL) {
153 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_EVP_LIB);
154 return 0;
155 }
156
157 RSA_up_ref(rsa);
158 EVP_PKEY_assign_RSA(pkey, rsa);
159
160 ret = ssl_set_pkey(ssl->cert, pkey);
161 EVP_PKEY_free(pkey);
162
163 return ret;
164}
165
166static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
167 int i;
168
169 i = ssl_cert_type(pkey);
170 if (i < 0) {
171 OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
172 return 0;
173 }
174
175 if (c->pkeys[i].x509 != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800176 /* Sanity-check that the private key and the certificate match, unless the
177 * key is opaque (in case of, say, a smartcard). */
178 if (!EVP_PKEY_is_opaque(pkey) &&
179 !X509_check_private_key(c->pkeys[i].x509, pkey)) {
180 X509_free(c->pkeys[i].x509);
181 c->pkeys[i].x509 = NULL;
182 return 0;
183 }
184 }
185
186 if (c->pkeys[i].privatekey != NULL) {
187 EVP_PKEY_free(c->pkeys[i].privatekey);
188 }
189 c->pkeys[i].privatekey = EVP_PKEY_dup(pkey);
190 c->key = &(c->pkeys[i]);
191
192 return 1;
193}
194
195int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
196 int reason_code, ret = 0;
197 BIO *in;
198 RSA *rsa = NULL;
199
200 in = BIO_new(BIO_s_file());
201 if (in == NULL) {
202 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_BUF_LIB);
203 goto end;
204 }
205
206 if (BIO_read_filename(in, file) <= 0) {
207 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_SYS_LIB);
208 goto end;
209 }
210
211 if (type == SSL_FILETYPE_ASN1) {
212 reason_code = ERR_R_ASN1_LIB;
213 rsa = d2i_RSAPrivateKey_bio(in, NULL);
214 } else if (type == SSL_FILETYPE_PEM) {
215 reason_code = ERR_R_PEM_LIB;
216 rsa =
217 PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
218 ssl->ctx->default_passwd_callback_userdata);
219 } else {
220 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
221 goto end;
222 }
223
224 if (rsa == NULL) {
225 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, reason_code);
226 goto end;
227 }
228 ret = SSL_use_RSAPrivateKey(ssl, rsa);
229 RSA_free(rsa);
230
231end:
232 if (in != NULL) {
233 BIO_free(in);
234 }
235 return ret;
236}
237
238int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, uint8_t *d, long len) {
239 int ret;
240 const uint8_t *p;
241 RSA *rsa;
242
243 p = d;
244 rsa = d2i_RSAPrivateKey(NULL, &p, (long)len);
245 if (rsa == NULL) {
246 OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB);
247 return 0;
248 }
249
250 ret = SSL_use_RSAPrivateKey(ssl, rsa);
251 RSA_free(rsa);
252 return ret;
253}
254
255int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
256 int ret;
257
258 if (pkey == NULL) {
259 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER);
260 return 0;
261 }
262
Adam Langleyfcf25832014-12-18 17:42:32 -0800263 ret = ssl_set_pkey(ssl->cert, pkey);
264 return ret;
265}
266
267int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
268 int reason_code, ret = 0;
269 BIO *in;
270 EVP_PKEY *pkey = NULL;
271
272 in = BIO_new(BIO_s_file());
273 if (in == NULL) {
274 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_BUF_LIB);
275 goto end;
276 }
277
278 if (BIO_read_filename(in, file) <= 0) {
279 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_SYS_LIB);
280 goto end;
281 }
282
283 if (type == SSL_FILETYPE_PEM) {
284 reason_code = ERR_R_PEM_LIB;
285 pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
286 ssl->ctx->default_passwd_callback_userdata);
287 } else if (type == SSL_FILETYPE_ASN1) {
288 reason_code = ERR_R_ASN1_LIB;
289 pkey = d2i_PrivateKey_bio(in, NULL);
290 } else {
291 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
292 goto end;
293 }
294
295 if (pkey == NULL) {
296 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, reason_code);
297 goto end;
298 }
299 ret = SSL_use_PrivateKey(ssl, pkey);
300 EVP_PKEY_free(pkey);
301
302end:
303 if (in != NULL) {
304 BIO_free(in);
305 }
306 return ret;
307}
308
309int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) {
310 int ret;
311 const uint8_t *p;
312 EVP_PKEY *pkey;
313
314 p = d;
315 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
316 if (pkey == NULL) {
317 OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_ASN1, ERR_R_ASN1_LIB);
318 return 0;
319 }
320
321 ret = SSL_use_PrivateKey(ssl, pkey);
322 EVP_PKEY_free(pkey);
323 return ret;
324}
325
326int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
327 if (x == NULL) {
328 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate,
329 ERR_R_PASSED_NULL_PARAMETER);
330 return 0;
331 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800332
333 return ssl_set_cert(ctx->cert, x);
334}
335
336static int ssl_set_cert(CERT *c, X509 *x) {
337 EVP_PKEY *pkey;
338 int i;
339
340 pkey = X509_get_pubkey(x);
341 if (pkey == NULL) {
342 OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB);
343 return 0;
344 }
345
346 i = ssl_cert_type(pkey);
347 if (i < 0) {
348 OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
349 EVP_PKEY_free(pkey);
350 return 0;
351 }
352
353 if (c->pkeys[i].privatekey != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800354 /* Sanity-check that the private key and the certificate match, unless the
355 * key is opaque (in case of, say, a smartcard). */
356 if (!EVP_PKEY_is_opaque(c->pkeys[i].privatekey) &&
357 !X509_check_private_key(x, c->pkeys[i].privatekey)) {
358 /* don't fail for a cert/key mismatch, just free current private key
359 * (when switching to a different cert & key, first this function should
360 * be used, then ssl_set_pkey */
361 EVP_PKEY_free(c->pkeys[i].privatekey);
362 c->pkeys[i].privatekey = NULL;
363 /* clear error queue */
364 ERR_clear_error();
365 }
366 }
367
368 EVP_PKEY_free(pkey);
369
370 if (c->pkeys[i].x509 != NULL) {
371 X509_free(c->pkeys[i].x509);
372 }
373 c->pkeys[i].x509 = X509_up_ref(x);
374 c->key = &(c->pkeys[i]);
375
376 return 1;
377}
378
379int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
380 int reason_code;
381 BIO *in;
382 int ret = 0;
383 X509 *x = NULL;
384
385 in = BIO_new(BIO_s_file());
386 if (in == NULL) {
387 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_BUF_LIB);
388 goto end;
389 }
390
391 if (BIO_read_filename(in, file) <= 0) {
392 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_SYS_LIB);
393 goto end;
394 }
395
396 if (type == SSL_FILETYPE_ASN1) {
397 reason_code = ERR_R_ASN1_LIB;
398 x = d2i_X509_bio(in, NULL);
399 } else if (type == SSL_FILETYPE_PEM) {
400 reason_code = ERR_R_PEM_LIB;
401 x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
402 ctx->default_passwd_callback_userdata);
403 } else {
404 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file,
405 SSL_R_BAD_SSL_FILETYPE);
406 goto end;
407 }
408
409 if (x == NULL) {
410 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, reason_code);
411 goto end;
412 }
413
414 ret = SSL_CTX_use_certificate(ctx, x);
415
416end:
417 if (x != NULL) {
418 X509_free(x);
419 }
420 if (in != NULL) {
421 BIO_free(in);
422 }
423 return ret;
424}
425
426int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) {
427 X509 *x;
428 int ret;
429
430 x = d2i_X509(NULL, &d, (long)len);
431 if (x == NULL) {
432 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_ASN1, ERR_R_ASN1_LIB);
433 return 0;
434 }
435
436 ret = SSL_CTX_use_certificate(ctx, x);
437 X509_free(x);
438 return ret;
439}
440
441int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
442 int ret;
443 EVP_PKEY *pkey;
444
445 if (rsa == NULL) {
446 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey,
447 ERR_R_PASSED_NULL_PARAMETER);
448 return 0;
449 }
450
Adam Langleyfcf25832014-12-18 17:42:32 -0800451 pkey = EVP_PKEY_new();
452 if (pkey == NULL) {
453 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_EVP_LIB);
454 return 0;
455 }
456
457 RSA_up_ref(rsa);
458 EVP_PKEY_assign_RSA(pkey, rsa);
459
460 ret = ssl_set_pkey(ctx->cert, pkey);
461 EVP_PKEY_free(pkey);
462 return ret;
463}
464
465int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
466 int reason_code, ret = 0;
467 BIO *in;
468 RSA *rsa = NULL;
469
470 in = BIO_new(BIO_s_file());
471 if (in == NULL) {
472 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_BUF_LIB);
473 goto end;
474 }
475
476 if (BIO_read_filename(in, file) <= 0) {
477 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_SYS_LIB);
478 goto end;
479 }
480
481 if (type == SSL_FILETYPE_ASN1) {
482 reason_code = ERR_R_ASN1_LIB;
483 rsa = d2i_RSAPrivateKey_bio(in, NULL);
484 } else if (type == SSL_FILETYPE_PEM) {
485 reason_code = ERR_R_PEM_LIB;
486 rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
487 ctx->default_passwd_callback_userdata);
488 } else {
489 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file,
490 SSL_R_BAD_SSL_FILETYPE);
491 goto end;
492 }
493
494 if (rsa == NULL) {
495 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, reason_code);
496 goto end;
497 }
498 ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
499 RSA_free(rsa);
500
501end:
502 if (in != NULL) {
503 BIO_free(in);
504 }
505 return ret;
506}
507
508int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *d, long len) {
509 int ret;
510 const uint8_t *p;
511 RSA *rsa;
512
513 p = d;
514 rsa = d2i_RSAPrivateKey(NULL, &p, (long)len);
515 if (rsa == NULL) {
516 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB);
517 return 0;
518 }
519
520 ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
521 RSA_free(rsa);
522 return ret;
523}
524
525int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
526 if (pkey == NULL) {
527 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER);
528 return 0;
529 }
530
Adam Langleyfcf25832014-12-18 17:42:32 -0800531 return ssl_set_pkey(ctx->cert, pkey);
532}
533
534int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
535 int reason_code, ret = 0;
536 BIO *in;
537 EVP_PKEY *pkey = NULL;
538
539 in = BIO_new(BIO_s_file());
540 if (in == NULL) {
541 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_BUF_LIB);
542 goto end;
543 }
544
545 if (BIO_read_filename(in, file) <= 0) {
546 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_SYS_LIB);
547 goto end;
548 }
549
550 if (type == SSL_FILETYPE_PEM) {
551 reason_code = ERR_R_PEM_LIB;
552 pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback,
553 ctx->default_passwd_callback_userdata);
554 } else if (type == SSL_FILETYPE_ASN1) {
555 reason_code = ERR_R_ASN1_LIB;
556 pkey = d2i_PrivateKey_bio(in, NULL);
557 } else {
558 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
559 goto end;
560 }
561
562 if (pkey == NULL) {
563 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, reason_code);
564 goto end;
565 }
566 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
567 EVP_PKEY_free(pkey);
568
569end:
570 if (in != NULL) {
571 BIO_free(in);
572 }
573 return ret;
574}
575
576int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d,
577 long len) {
578 int ret;
579 const uint8_t *p;
580 EVP_PKEY *pkey;
581
582 p = d;
583 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
584 if (pkey == NULL) {
585 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_ASN1, ERR_R_ASN1_LIB);
586 return 0;
587 }
588
589 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
590 EVP_PKEY_free(pkey);
591 return ret;
592}
593
594
595/* Read a file that contains our certificate in "PEM" format, possibly followed
596 * by a sequence of CA certificates that should be sent to the peer in the
597 * Certificate message. */
598int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
599 BIO *in;
600 int ret = 0;
601 X509 *x = NULL;
602
603 ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
604
605 in = BIO_new(BIO_s_file());
606 if (in == NULL) {
607 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_BUF_LIB);
608 goto end;
609 }
610
611 if (BIO_read_filename(in, file) <= 0) {
612 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_SYS_LIB);
613 goto end;
614 }
615
616 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
617 ctx->default_passwd_callback_userdata);
618 if (x == NULL) {
619 OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_PEM_LIB);
620 goto end;
621 }
622
623 ret = SSL_CTX_use_certificate(ctx, x);
624
625 if (ERR_peek_error() != 0) {
626 ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
627 }
628
629 if (ret) {
630 /* If we could set up our certificate, now proceed to the CA
631 * certificates. */
632 X509 *ca;
633 int r;
634 unsigned long err;
635
636 SSL_CTX_clear_chain_certs(ctx);
637
638 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
639 ctx->default_passwd_callback_userdata)) !=
640 NULL) {
641 r = SSL_CTX_add0_chain_cert(ctx, ca);
642 if (!r) {
643 X509_free(ca);
644 ret = 0;
645 goto end;
646 }
647 /* Note that we must not free r if it was successfully added to the chain
648 * (while we must free the main certificate, since its reference count is
649 * increased by SSL_CTX_use_certificate). */
650 }
651
652 /* When the while loop ends, it's usually just EOF. */
653 err = ERR_peek_last_error();
654 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
655 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
656 ERR_clear_error();
657 } else {
658 ret = 0; /* some real error */
659 }
660 }
661
662end:
663 if (x != NULL) {
664 X509_free(x);
665 }
666 if (in != NULL) {
667 BIO_free(in);
668 }
669 return ret;
670}