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