xref: /dragonfly/crypto/libressl/ssl/ssl_rsa.c (revision de0e0e4d)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: ssl_rsa.c,v 1.48 2022/08/31 20:49:37 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #include <stdio.h>
60f5b1c8a1SJohn Marino 
61f5b1c8a1SJohn Marino #include <openssl/bio.h>
62f5b1c8a1SJohn Marino #include <openssl/evp.h>
63f5b1c8a1SJohn Marino #include <openssl/objects.h>
64f5b1c8a1SJohn Marino #include <openssl/pem.h>
65f5b1c8a1SJohn Marino #include <openssl/x509.h>
66f5b1c8a1SJohn Marino 
67*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
68*de0e0e4dSAntonio Huete Jimenez 
69*de0e0e4dSAntonio Huete Jimenez static int ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl,
70*de0e0e4dSAntonio Huete Jimenez     pem_password_cb **passwd_cb, void **passwd_arg);
71*de0e0e4dSAntonio Huete Jimenez static int ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x509);
72*de0e0e4dSAntonio Huete Jimenez static int ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey);
73*de0e0e4dSAntonio Huete Jimenez static int ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in);
74*de0e0e4dSAntonio Huete Jimenez static int ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl,
75*de0e0e4dSAntonio Huete Jimenez     const char *file);
76f5b1c8a1SJohn Marino 
77f5b1c8a1SJohn Marino int
SSL_use_certificate(SSL * ssl,X509 * x)78f5b1c8a1SJohn Marino SSL_use_certificate(SSL *ssl, X509 *x)
79f5b1c8a1SJohn Marino {
80f5b1c8a1SJohn Marino 	if (x == NULL) {
8172c33676SMaxim Ag 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
82f5b1c8a1SJohn Marino 		return (0);
83f5b1c8a1SJohn Marino 	}
84*de0e0e4dSAntonio Huete Jimenez 	return ssl_set_cert(NULL, ssl, x);
85f5b1c8a1SJohn Marino }
86f5b1c8a1SJohn Marino 
87f5b1c8a1SJohn Marino int
SSL_use_certificate_file(SSL * ssl,const char * file,int type)88f5b1c8a1SJohn Marino SSL_use_certificate_file(SSL *ssl, const char *file, int type)
89f5b1c8a1SJohn Marino {
90f5b1c8a1SJohn Marino 	int j;
91f5b1c8a1SJohn Marino 	BIO *in;
92f5b1c8a1SJohn Marino 	int ret = 0;
93f5b1c8a1SJohn Marino 	X509 *x = NULL;
94f5b1c8a1SJohn Marino 
95*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
96f5b1c8a1SJohn Marino 	if (in == NULL) {
9772c33676SMaxim Ag 		SSLerror(ssl, ERR_R_BUF_LIB);
98f5b1c8a1SJohn Marino 		goto end;
99f5b1c8a1SJohn Marino 	}
100f5b1c8a1SJohn Marino 
101f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
10272c33676SMaxim Ag 		SSLerror(ssl, ERR_R_SYS_LIB);
103f5b1c8a1SJohn Marino 		goto end;
104f5b1c8a1SJohn Marino 	}
105f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_ASN1) {
106f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
107f5b1c8a1SJohn Marino 		x = d2i_X509_bio(in, NULL);
108f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_PEM) {
109f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
110f5b1c8a1SJohn Marino 		x = PEM_read_bio_X509(in, NULL,
111f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback,
112f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback_userdata);
113f5b1c8a1SJohn Marino 	} else {
11472c33676SMaxim Ag 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
115f5b1c8a1SJohn Marino 		goto end;
116f5b1c8a1SJohn Marino 	}
117f5b1c8a1SJohn Marino 
118f5b1c8a1SJohn Marino 	if (x == NULL) {
11972c33676SMaxim Ag 		SSLerror(ssl, j);
120f5b1c8a1SJohn Marino 		goto end;
121f5b1c8a1SJohn Marino 	}
122f5b1c8a1SJohn Marino 
123f5b1c8a1SJohn Marino 	ret = SSL_use_certificate(ssl, x);
124f5b1c8a1SJohn Marino  end:
125f5b1c8a1SJohn Marino 	X509_free(x);
126f5b1c8a1SJohn Marino 	BIO_free(in);
127f5b1c8a1SJohn Marino 	return (ret);
128f5b1c8a1SJohn Marino }
129f5b1c8a1SJohn Marino 
130f5b1c8a1SJohn Marino int
SSL_use_certificate_ASN1(SSL * ssl,const unsigned char * d,int len)131f5b1c8a1SJohn Marino SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
132f5b1c8a1SJohn Marino {
133f5b1c8a1SJohn Marino 	X509 *x;
134f5b1c8a1SJohn Marino 	int ret;
135f5b1c8a1SJohn Marino 
136f5b1c8a1SJohn Marino 	x = d2i_X509(NULL, &d, (long)len);
137f5b1c8a1SJohn Marino 	if (x == NULL) {
13872c33676SMaxim Ag 		SSLerror(ssl, ERR_R_ASN1_LIB);
139f5b1c8a1SJohn Marino 		return (0);
140f5b1c8a1SJohn Marino 	}
141f5b1c8a1SJohn Marino 
142f5b1c8a1SJohn Marino 	ret = SSL_use_certificate(ssl, x);
143f5b1c8a1SJohn Marino 	X509_free(x);
144f5b1c8a1SJohn Marino 	return (ret);
145f5b1c8a1SJohn Marino }
146f5b1c8a1SJohn Marino 
147f5b1c8a1SJohn Marino int
SSL_use_RSAPrivateKey(SSL * ssl,RSA * rsa)148f5b1c8a1SJohn Marino SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
149f5b1c8a1SJohn Marino {
150f5b1c8a1SJohn Marino 	EVP_PKEY *pkey;
151f5b1c8a1SJohn Marino 	int ret;
152f5b1c8a1SJohn Marino 
153f5b1c8a1SJohn Marino 	if (rsa == NULL) {
15472c33676SMaxim Ag 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
155f5b1c8a1SJohn Marino 		return (0);
156f5b1c8a1SJohn Marino 	}
157f5b1c8a1SJohn Marino 	if ((pkey = EVP_PKEY_new()) == NULL) {
15872c33676SMaxim Ag 		SSLerror(ssl, ERR_R_EVP_LIB);
159f5b1c8a1SJohn Marino 		return (0);
160f5b1c8a1SJohn Marino 	}
161f5b1c8a1SJohn Marino 
162f5b1c8a1SJohn Marino 	RSA_up_ref(rsa);
163f5b1c8a1SJohn Marino 	EVP_PKEY_assign_RSA(pkey, rsa);
164f5b1c8a1SJohn Marino 
165*de0e0e4dSAntonio Huete Jimenez 	ret = ssl_set_pkey(NULL, ssl, pkey);
166f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
167f5b1c8a1SJohn Marino 	return (ret);
168f5b1c8a1SJohn Marino }
169f5b1c8a1SJohn Marino 
170f5b1c8a1SJohn Marino static int
ssl_set_pkey(SSL_CTX * ctx,SSL * ssl,EVP_PKEY * pkey)171*de0e0e4dSAntonio Huete Jimenez ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey)
172f5b1c8a1SJohn Marino {
173*de0e0e4dSAntonio Huete Jimenez 	SSL_CERT *c;
174f5b1c8a1SJohn Marino 	int i;
175f5b1c8a1SJohn Marino 
176*de0e0e4dSAntonio Huete Jimenez 	i = ssl_cert_type(pkey);
177f5b1c8a1SJohn Marino 	if (i < 0) {
17872c33676SMaxim Ag 		SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE);
179f5b1c8a1SJohn Marino 		return (0);
180f5b1c8a1SJohn Marino 	}
181f5b1c8a1SJohn Marino 
182*de0e0e4dSAntonio Huete Jimenez 	if ((c = ssl_get0_cert(ctx, ssl)) == NULL)
183*de0e0e4dSAntonio Huete Jimenez 		return (0);
184*de0e0e4dSAntonio Huete Jimenez 
185f5b1c8a1SJohn Marino 	if (c->pkeys[i].x509 != NULL) {
186f5b1c8a1SJohn Marino 		EVP_PKEY *pktmp;
187*de0e0e4dSAntonio Huete Jimenez 
188*de0e0e4dSAntonio Huete Jimenez 		if ((pktmp = X509_get0_pubkey(c->pkeys[i].x509)) == NULL)
189*de0e0e4dSAntonio Huete Jimenez 			return 0;
190*de0e0e4dSAntonio Huete Jimenez 
191*de0e0e4dSAntonio Huete Jimenez 		/*
192*de0e0e4dSAntonio Huete Jimenez 		 * Callers of EVP_PKEY_copy_parameters() can't distinguish
193*de0e0e4dSAntonio Huete Jimenez 		 * errors from the absence of a param_copy() method. So
194*de0e0e4dSAntonio Huete Jimenez 		 * pretend it can never fail.
195*de0e0e4dSAntonio Huete Jimenez 		 */
196f5b1c8a1SJohn Marino 		EVP_PKEY_copy_parameters(pktmp, pkey);
197*de0e0e4dSAntonio Huete Jimenez 
198f5b1c8a1SJohn Marino 		ERR_clear_error();
199f5b1c8a1SJohn Marino 
200f5b1c8a1SJohn Marino 		/*
201f5b1c8a1SJohn Marino 		 * Don't check the public/private key, this is mostly
202f5b1c8a1SJohn Marino 		 * for smart cards.
203f5b1c8a1SJohn Marino 		 */
204*de0e0e4dSAntonio Huete Jimenez 		if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA ||
205*de0e0e4dSAntonio Huete Jimenez 		    !(RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK)) {
206f5b1c8a1SJohn Marino 			if (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
207f5b1c8a1SJohn Marino 				X509_free(c->pkeys[i].x509);
208f5b1c8a1SJohn Marino 				c->pkeys[i].x509 = NULL;
209f5b1c8a1SJohn Marino 				return 0;
210f5b1c8a1SJohn Marino 			}
211f5b1c8a1SJohn Marino 		}
212*de0e0e4dSAntonio Huete Jimenez 	}
213f5b1c8a1SJohn Marino 
214f5b1c8a1SJohn Marino 	EVP_PKEY_free(c->pkeys[i].privatekey);
215*de0e0e4dSAntonio Huete Jimenez 	EVP_PKEY_up_ref(pkey);
216f5b1c8a1SJohn Marino 	c->pkeys[i].privatekey = pkey;
217f5b1c8a1SJohn Marino 	c->key = &(c->pkeys[i]);
218f5b1c8a1SJohn Marino 
219f5b1c8a1SJohn Marino 	c->valid = 0;
220*de0e0e4dSAntonio Huete Jimenez 	return 1;
221f5b1c8a1SJohn Marino }
222f5b1c8a1SJohn Marino 
223f5b1c8a1SJohn Marino int
SSL_use_RSAPrivateKey_file(SSL * ssl,const char * file,int type)224f5b1c8a1SJohn Marino SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
225f5b1c8a1SJohn Marino {
226f5b1c8a1SJohn Marino 	int j, ret = 0;
227f5b1c8a1SJohn Marino 	BIO *in;
228f5b1c8a1SJohn Marino 	RSA *rsa = NULL;
229f5b1c8a1SJohn Marino 
230*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
231f5b1c8a1SJohn Marino 	if (in == NULL) {
23272c33676SMaxim Ag 		SSLerror(ssl, ERR_R_BUF_LIB);
233f5b1c8a1SJohn Marino 		goto end;
234f5b1c8a1SJohn Marino 	}
235f5b1c8a1SJohn Marino 
236f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
23772c33676SMaxim Ag 		SSLerror(ssl, ERR_R_SYS_LIB);
238f5b1c8a1SJohn Marino 		goto end;
239f5b1c8a1SJohn Marino 	}
240f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_ASN1) {
241f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
242f5b1c8a1SJohn Marino 		rsa = d2i_RSAPrivateKey_bio(in, NULL);
243f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_PEM) {
244f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
245f5b1c8a1SJohn Marino 		rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
246f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback,
247f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback_userdata);
248f5b1c8a1SJohn Marino 	} else {
24972c33676SMaxim Ag 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
250f5b1c8a1SJohn Marino 		goto end;
251f5b1c8a1SJohn Marino 	}
252f5b1c8a1SJohn Marino 	if (rsa == NULL) {
25372c33676SMaxim Ag 		SSLerror(ssl, j);
254f5b1c8a1SJohn Marino 		goto end;
255f5b1c8a1SJohn Marino 	}
256f5b1c8a1SJohn Marino 	ret = SSL_use_RSAPrivateKey(ssl, rsa);
257f5b1c8a1SJohn Marino 	RSA_free(rsa);
258f5b1c8a1SJohn Marino  end:
259f5b1c8a1SJohn Marino 	BIO_free(in);
260f5b1c8a1SJohn Marino 	return (ret);
261f5b1c8a1SJohn Marino }
262f5b1c8a1SJohn Marino 
263f5b1c8a1SJohn Marino int
SSL_use_RSAPrivateKey_ASN1(SSL * ssl,const unsigned char * d,long len)26472c33676SMaxim Ag SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
265f5b1c8a1SJohn Marino {
266f5b1c8a1SJohn Marino 	int ret;
267f5b1c8a1SJohn Marino 	RSA *rsa;
268f5b1c8a1SJohn Marino 
26972c33676SMaxim Ag 	if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) {
27072c33676SMaxim Ag 		SSLerror(ssl, ERR_R_ASN1_LIB);
271f5b1c8a1SJohn Marino 		return (0);
272f5b1c8a1SJohn Marino 	}
273f5b1c8a1SJohn Marino 
274f5b1c8a1SJohn Marino 	ret = SSL_use_RSAPrivateKey(ssl, rsa);
275f5b1c8a1SJohn Marino 	RSA_free(rsa);
276f5b1c8a1SJohn Marino 	return (ret);
277f5b1c8a1SJohn Marino }
278f5b1c8a1SJohn Marino 
279f5b1c8a1SJohn Marino int
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)280f5b1c8a1SJohn Marino SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
281f5b1c8a1SJohn Marino {
282f5b1c8a1SJohn Marino 	int ret;
283f5b1c8a1SJohn Marino 
284f5b1c8a1SJohn Marino 	if (pkey == NULL) {
28572c33676SMaxim Ag 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
286f5b1c8a1SJohn Marino 		return (0);
287f5b1c8a1SJohn Marino 	}
288*de0e0e4dSAntonio Huete Jimenez 	ret = ssl_set_pkey(NULL, ssl, pkey);
289f5b1c8a1SJohn Marino 	return (ret);
290f5b1c8a1SJohn Marino }
291f5b1c8a1SJohn Marino 
292f5b1c8a1SJohn Marino int
SSL_use_PrivateKey_file(SSL * ssl,const char * file,int type)293f5b1c8a1SJohn Marino SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
294f5b1c8a1SJohn Marino {
295f5b1c8a1SJohn Marino 	int j, ret = 0;
296f5b1c8a1SJohn Marino 	BIO *in;
297f5b1c8a1SJohn Marino 	EVP_PKEY *pkey = NULL;
298f5b1c8a1SJohn Marino 
299*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
300f5b1c8a1SJohn Marino 	if (in == NULL) {
30172c33676SMaxim Ag 		SSLerror(ssl, ERR_R_BUF_LIB);
302f5b1c8a1SJohn Marino 		goto end;
303f5b1c8a1SJohn Marino 	}
304f5b1c8a1SJohn Marino 
305f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
30672c33676SMaxim Ag 		SSLerror(ssl, ERR_R_SYS_LIB);
307f5b1c8a1SJohn Marino 		goto end;
308f5b1c8a1SJohn Marino 	}
309f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_PEM) {
310f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
311f5b1c8a1SJohn Marino 		pkey = PEM_read_bio_PrivateKey(in, NULL,
312f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback,
313f5b1c8a1SJohn Marino 		    ssl->ctx->default_passwd_callback_userdata);
314f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_ASN1) {
315f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
316f5b1c8a1SJohn Marino 		pkey = d2i_PrivateKey_bio(in, NULL);
317f5b1c8a1SJohn Marino 	} else {
31872c33676SMaxim Ag 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
319f5b1c8a1SJohn Marino 		goto end;
320f5b1c8a1SJohn Marino 	}
321f5b1c8a1SJohn Marino 	if (pkey == NULL) {
32272c33676SMaxim Ag 		SSLerror(ssl, j);
323f5b1c8a1SJohn Marino 		goto end;
324f5b1c8a1SJohn Marino 	}
325f5b1c8a1SJohn Marino 	ret = SSL_use_PrivateKey(ssl, pkey);
326f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
327f5b1c8a1SJohn Marino  end:
328f5b1c8a1SJohn Marino 	BIO_free(in);
329f5b1c8a1SJohn Marino 	return (ret);
330f5b1c8a1SJohn Marino }
331f5b1c8a1SJohn Marino 
332f5b1c8a1SJohn Marino int
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const unsigned char * d,long len)333f5b1c8a1SJohn Marino SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len)
334f5b1c8a1SJohn Marino {
335f5b1c8a1SJohn Marino 	int ret;
336f5b1c8a1SJohn Marino 	EVP_PKEY *pkey;
337f5b1c8a1SJohn Marino 
33872c33676SMaxim Ag 	if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) {
33972c33676SMaxim Ag 		SSLerror(ssl, ERR_R_ASN1_LIB);
340f5b1c8a1SJohn Marino 		return (0);
341f5b1c8a1SJohn Marino 	}
342f5b1c8a1SJohn Marino 
343f5b1c8a1SJohn Marino 	ret = SSL_use_PrivateKey(ssl, pkey);
344f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
345f5b1c8a1SJohn Marino 	return (ret);
346f5b1c8a1SJohn Marino }
347f5b1c8a1SJohn Marino 
348f5b1c8a1SJohn Marino int
SSL_CTX_use_certificate(SSL_CTX * ctx,X509 * x)349f5b1c8a1SJohn Marino SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
350f5b1c8a1SJohn Marino {
351f5b1c8a1SJohn Marino 	if (x == NULL) {
35272c33676SMaxim Ag 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
353f5b1c8a1SJohn Marino 		return (0);
354f5b1c8a1SJohn Marino 	}
355*de0e0e4dSAntonio Huete Jimenez 	return ssl_set_cert(ctx, NULL, x);
356f5b1c8a1SJohn Marino }
357f5b1c8a1SJohn Marino 
358f5b1c8a1SJohn Marino static int
ssl_get_password_cb_and_arg(SSL_CTX * ctx,SSL * ssl,pem_password_cb ** passwd_cb,void ** passwd_arg)359*de0e0e4dSAntonio Huete Jimenez ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl,
360*de0e0e4dSAntonio Huete Jimenez     pem_password_cb **passwd_cb, void **passwd_arg)
361f5b1c8a1SJohn Marino {
362*de0e0e4dSAntonio Huete Jimenez 	if (ssl != NULL)
363*de0e0e4dSAntonio Huete Jimenez 		ctx = ssl->ctx;
364*de0e0e4dSAntonio Huete Jimenez 
365*de0e0e4dSAntonio Huete Jimenez 	*passwd_cb = ctx->default_passwd_callback;
366*de0e0e4dSAntonio Huete Jimenez 	*passwd_arg = ctx->default_passwd_callback_userdata;
367*de0e0e4dSAntonio Huete Jimenez 
368*de0e0e4dSAntonio Huete Jimenez 	return 1;
369*de0e0e4dSAntonio Huete Jimenez }
370*de0e0e4dSAntonio Huete Jimenez 
371*de0e0e4dSAntonio Huete Jimenez static int
ssl_set_cert(SSL_CTX * ctx,SSL * ssl,X509 * x)372*de0e0e4dSAntonio Huete Jimenez ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x)
373*de0e0e4dSAntonio Huete Jimenez {
374*de0e0e4dSAntonio Huete Jimenez 	SSL_CERT *c;
375f5b1c8a1SJohn Marino 	EVP_PKEY *pkey;
376*de0e0e4dSAntonio Huete Jimenez 	int ssl_err;
377f5b1c8a1SJohn Marino 	int i;
378f5b1c8a1SJohn Marino 
379*de0e0e4dSAntonio Huete Jimenez 	if (!ssl_security_cert(ctx, ssl, x, 1, &ssl_err)) {
380*de0e0e4dSAntonio Huete Jimenez 		SSLerrorx(ssl_err);
381*de0e0e4dSAntonio Huete Jimenez 		return (0);
382*de0e0e4dSAntonio Huete Jimenez 	}
383*de0e0e4dSAntonio Huete Jimenez 
384*de0e0e4dSAntonio Huete Jimenez 	if ((c = ssl_get0_cert(ctx, ssl)) == NULL)
385*de0e0e4dSAntonio Huete Jimenez 		return (0);
386*de0e0e4dSAntonio Huete Jimenez 
387f5b1c8a1SJohn Marino 	pkey = X509_get_pubkey(x);
388f5b1c8a1SJohn Marino 	if (pkey == NULL) {
38972c33676SMaxim Ag 		SSLerrorx(SSL_R_X509_LIB);
390f5b1c8a1SJohn Marino 		return (0);
391f5b1c8a1SJohn Marino 	}
392f5b1c8a1SJohn Marino 
393*de0e0e4dSAntonio Huete Jimenez 	i = ssl_cert_type(pkey);
394f5b1c8a1SJohn Marino 	if (i < 0) {
39572c33676SMaxim Ag 		SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE);
396f5b1c8a1SJohn Marino 		EVP_PKEY_free(pkey);
397f5b1c8a1SJohn Marino 		return (0);
398f5b1c8a1SJohn Marino 	}
399f5b1c8a1SJohn Marino 
400f5b1c8a1SJohn Marino 	if (c->pkeys[i].privatekey != NULL) {
401*de0e0e4dSAntonio Huete Jimenez 		EVP_PKEY *priv_key = c->pkeys[i].privatekey;
402*de0e0e4dSAntonio Huete Jimenez 
403*de0e0e4dSAntonio Huete Jimenez 		EVP_PKEY_copy_parameters(pkey, priv_key);
404f5b1c8a1SJohn Marino 		ERR_clear_error();
405f5b1c8a1SJohn Marino 
406f5b1c8a1SJohn Marino 		/*
407f5b1c8a1SJohn Marino 		 * Don't check the public/private key, this is mostly
408f5b1c8a1SJohn Marino 		 * for smart cards.
409f5b1c8a1SJohn Marino 		 */
410*de0e0e4dSAntonio Huete Jimenez 		if (EVP_PKEY_id(priv_key) != EVP_PKEY_RSA ||
411*de0e0e4dSAntonio Huete Jimenez 		    !(RSA_flags(EVP_PKEY_get0_RSA(priv_key)) & RSA_METHOD_FLAG_NO_CHECK)) {
412*de0e0e4dSAntonio Huete Jimenez 			if (!X509_check_private_key(x, priv_key)) {
413f5b1c8a1SJohn Marino 				/*
414f5b1c8a1SJohn Marino 				 * don't fail for a cert/key mismatch, just free
415*de0e0e4dSAntonio Huete Jimenez 				 * current private key (when switching to a
416*de0e0e4dSAntonio Huete Jimenez 				 * different cert & key, first this function
417*de0e0e4dSAntonio Huete Jimenez 				 * should be used, then ssl_set_pkey.
418f5b1c8a1SJohn Marino 				 */
419f5b1c8a1SJohn Marino 				EVP_PKEY_free(c->pkeys[i].privatekey);
420f5b1c8a1SJohn Marino 				c->pkeys[i].privatekey = NULL;
421f5b1c8a1SJohn Marino 				ERR_clear_error();
422f5b1c8a1SJohn Marino 			}
423f5b1c8a1SJohn Marino 		}
424*de0e0e4dSAntonio Huete Jimenez 	}
425f5b1c8a1SJohn Marino 
426f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
427f5b1c8a1SJohn Marino 
428f5b1c8a1SJohn Marino 	X509_free(c->pkeys[i].x509);
429*de0e0e4dSAntonio Huete Jimenez 	X509_up_ref(x);
430f5b1c8a1SJohn Marino 	c->pkeys[i].x509 = x;
431f5b1c8a1SJohn Marino 	c->key = &(c->pkeys[i]);
432f5b1c8a1SJohn Marino 
433f5b1c8a1SJohn Marino 	c->valid = 0;
434f5b1c8a1SJohn Marino 	return (1);
435f5b1c8a1SJohn Marino }
436f5b1c8a1SJohn Marino 
437f5b1c8a1SJohn Marino int
SSL_CTX_use_certificate_file(SSL_CTX * ctx,const char * file,int type)438f5b1c8a1SJohn Marino SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
439f5b1c8a1SJohn Marino {
440f5b1c8a1SJohn Marino 	int j;
441f5b1c8a1SJohn Marino 	BIO *in;
442f5b1c8a1SJohn Marino 	int ret = 0;
443f5b1c8a1SJohn Marino 	X509 *x = NULL;
444f5b1c8a1SJohn Marino 
445*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
446f5b1c8a1SJohn Marino 	if (in == NULL) {
44772c33676SMaxim Ag 		SSLerrorx(ERR_R_BUF_LIB);
448f5b1c8a1SJohn Marino 		goto end;
449f5b1c8a1SJohn Marino 	}
450f5b1c8a1SJohn Marino 
451f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
45272c33676SMaxim Ag 		SSLerrorx(ERR_R_SYS_LIB);
453f5b1c8a1SJohn Marino 		goto end;
454f5b1c8a1SJohn Marino 	}
455f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_ASN1) {
456f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
457f5b1c8a1SJohn Marino 		x = d2i_X509_bio(in, NULL);
458f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_PEM) {
459f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
460f5b1c8a1SJohn Marino 		x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
461f5b1c8a1SJohn Marino 		    ctx->default_passwd_callback_userdata);
462f5b1c8a1SJohn Marino 	} else {
46372c33676SMaxim Ag 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
464f5b1c8a1SJohn Marino 		goto end;
465f5b1c8a1SJohn Marino 	}
466f5b1c8a1SJohn Marino 
467f5b1c8a1SJohn Marino 	if (x == NULL) {
46872c33676SMaxim Ag 		SSLerrorx(j);
469f5b1c8a1SJohn Marino 		goto end;
470f5b1c8a1SJohn Marino 	}
471f5b1c8a1SJohn Marino 
472f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_certificate(ctx, x);
473f5b1c8a1SJohn Marino  end:
474f5b1c8a1SJohn Marino 	X509_free(x);
475f5b1c8a1SJohn Marino 	BIO_free(in);
476f5b1c8a1SJohn Marino 	return (ret);
477f5b1c8a1SJohn Marino }
478f5b1c8a1SJohn Marino 
479f5b1c8a1SJohn Marino int
SSL_CTX_use_certificate_ASN1(SSL_CTX * ctx,int len,const unsigned char * d)480f5b1c8a1SJohn Marino SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
481f5b1c8a1SJohn Marino {
482f5b1c8a1SJohn Marino 	X509 *x;
483f5b1c8a1SJohn Marino 	int ret;
484f5b1c8a1SJohn Marino 
485f5b1c8a1SJohn Marino 	x = d2i_X509(NULL, &d, (long)len);
486f5b1c8a1SJohn Marino 	if (x == NULL) {
48772c33676SMaxim Ag 		SSLerrorx(ERR_R_ASN1_LIB);
488f5b1c8a1SJohn Marino 		return (0);
489f5b1c8a1SJohn Marino 	}
490f5b1c8a1SJohn Marino 
491f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_certificate(ctx, x);
492f5b1c8a1SJohn Marino 	X509_free(x);
493f5b1c8a1SJohn Marino 	return (ret);
494f5b1c8a1SJohn Marino }
495f5b1c8a1SJohn Marino 
496f5b1c8a1SJohn Marino int
SSL_CTX_use_RSAPrivateKey(SSL_CTX * ctx,RSA * rsa)497f5b1c8a1SJohn Marino SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
498f5b1c8a1SJohn Marino {
499f5b1c8a1SJohn Marino 	int ret;
500f5b1c8a1SJohn Marino 	EVP_PKEY *pkey;
501f5b1c8a1SJohn Marino 
502f5b1c8a1SJohn Marino 	if (rsa == NULL) {
50372c33676SMaxim Ag 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
504f5b1c8a1SJohn Marino 		return (0);
505f5b1c8a1SJohn Marino 	}
506f5b1c8a1SJohn Marino 	if ((pkey = EVP_PKEY_new()) == NULL) {
50772c33676SMaxim Ag 		SSLerrorx(ERR_R_EVP_LIB);
508f5b1c8a1SJohn Marino 		return (0);
509f5b1c8a1SJohn Marino 	}
510f5b1c8a1SJohn Marino 
511f5b1c8a1SJohn Marino 	RSA_up_ref(rsa);
512f5b1c8a1SJohn Marino 	EVP_PKEY_assign_RSA(pkey, rsa);
513f5b1c8a1SJohn Marino 
514*de0e0e4dSAntonio Huete Jimenez 	ret = ssl_set_pkey(ctx, NULL, pkey);
515f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
516f5b1c8a1SJohn Marino 	return (ret);
517f5b1c8a1SJohn Marino }
518f5b1c8a1SJohn Marino 
519f5b1c8a1SJohn Marino int
SSL_CTX_use_RSAPrivateKey_file(SSL_CTX * ctx,const char * file,int type)520f5b1c8a1SJohn Marino SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
521f5b1c8a1SJohn Marino {
522f5b1c8a1SJohn Marino 	int j, ret = 0;
523f5b1c8a1SJohn Marino 	BIO *in;
524f5b1c8a1SJohn Marino 	RSA *rsa = NULL;
525f5b1c8a1SJohn Marino 
526*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
527f5b1c8a1SJohn Marino 	if (in == NULL) {
52872c33676SMaxim Ag 		SSLerrorx(ERR_R_BUF_LIB);
529f5b1c8a1SJohn Marino 		goto end;
530f5b1c8a1SJohn Marino 	}
531f5b1c8a1SJohn Marino 
532f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
53372c33676SMaxim Ag 		SSLerrorx(ERR_R_SYS_LIB);
534f5b1c8a1SJohn Marino 		goto end;
535f5b1c8a1SJohn Marino 	}
536f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_ASN1) {
537f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
538f5b1c8a1SJohn Marino 		rsa = d2i_RSAPrivateKey_bio(in, NULL);
539f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_PEM) {
540f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
541f5b1c8a1SJohn Marino 		rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
542f5b1c8a1SJohn Marino 		    ctx->default_passwd_callback,
543f5b1c8a1SJohn Marino 		    ctx->default_passwd_callback_userdata);
544f5b1c8a1SJohn Marino 	} else {
54572c33676SMaxim Ag 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
546f5b1c8a1SJohn Marino 		goto end;
547f5b1c8a1SJohn Marino 	}
548f5b1c8a1SJohn Marino 	if (rsa == NULL) {
54972c33676SMaxim Ag 		SSLerrorx(j);
550f5b1c8a1SJohn Marino 		goto end;
551f5b1c8a1SJohn Marino 	}
552f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
553f5b1c8a1SJohn Marino 	RSA_free(rsa);
554f5b1c8a1SJohn Marino  end:
555f5b1c8a1SJohn Marino 	BIO_free(in);
556f5b1c8a1SJohn Marino 	return (ret);
557f5b1c8a1SJohn Marino }
558f5b1c8a1SJohn Marino 
559f5b1c8a1SJohn Marino int
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const unsigned char * d,long len)560f5b1c8a1SJohn Marino SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
561f5b1c8a1SJohn Marino {
562f5b1c8a1SJohn Marino 	int ret;
563f5b1c8a1SJohn Marino 	RSA *rsa;
564f5b1c8a1SJohn Marino 
56572c33676SMaxim Ag 	if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) {
56672c33676SMaxim Ag 		SSLerrorx(ERR_R_ASN1_LIB);
567f5b1c8a1SJohn Marino 		return (0);
568f5b1c8a1SJohn Marino 	}
569f5b1c8a1SJohn Marino 
570f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
571f5b1c8a1SJohn Marino 	RSA_free(rsa);
572f5b1c8a1SJohn Marino 	return (ret);
573f5b1c8a1SJohn Marino }
574f5b1c8a1SJohn Marino 
575f5b1c8a1SJohn Marino int
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)576f5b1c8a1SJohn Marino SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
577f5b1c8a1SJohn Marino {
578f5b1c8a1SJohn Marino 	if (pkey == NULL) {
57972c33676SMaxim Ag 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
580f5b1c8a1SJohn Marino 		return (0);
581f5b1c8a1SJohn Marino 	}
582*de0e0e4dSAntonio Huete Jimenez 	return ssl_set_pkey(ctx, NULL, pkey);
583f5b1c8a1SJohn Marino }
584f5b1c8a1SJohn Marino 
585f5b1c8a1SJohn Marino int
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)586f5b1c8a1SJohn Marino SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
587f5b1c8a1SJohn Marino {
588f5b1c8a1SJohn Marino 	int j, ret = 0;
589f5b1c8a1SJohn Marino 	BIO *in;
590f5b1c8a1SJohn Marino 	EVP_PKEY *pkey = NULL;
591f5b1c8a1SJohn Marino 
592*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
593f5b1c8a1SJohn Marino 	if (in == NULL) {
59472c33676SMaxim Ag 		SSLerrorx(ERR_R_BUF_LIB);
595f5b1c8a1SJohn Marino 		goto end;
596f5b1c8a1SJohn Marino 	}
597f5b1c8a1SJohn Marino 
598f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
59972c33676SMaxim Ag 		SSLerrorx(ERR_R_SYS_LIB);
600f5b1c8a1SJohn Marino 		goto end;
601f5b1c8a1SJohn Marino 	}
602f5b1c8a1SJohn Marino 	if (type == SSL_FILETYPE_PEM) {
603f5b1c8a1SJohn Marino 		j = ERR_R_PEM_LIB;
604f5b1c8a1SJohn Marino 		pkey = PEM_read_bio_PrivateKey(in, NULL,
605f5b1c8a1SJohn Marino 		    ctx->default_passwd_callback,
606f5b1c8a1SJohn Marino 		    ctx->default_passwd_callback_userdata);
607f5b1c8a1SJohn Marino 	} else if (type == SSL_FILETYPE_ASN1) {
608f5b1c8a1SJohn Marino 		j = ERR_R_ASN1_LIB;
609f5b1c8a1SJohn Marino 		pkey = d2i_PrivateKey_bio(in, NULL);
610f5b1c8a1SJohn Marino 	} else {
61172c33676SMaxim Ag 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
612f5b1c8a1SJohn Marino 		goto end;
613f5b1c8a1SJohn Marino 	}
614f5b1c8a1SJohn Marino 	if (pkey == NULL) {
61572c33676SMaxim Ag 		SSLerrorx(j);
616f5b1c8a1SJohn Marino 		goto end;
617f5b1c8a1SJohn Marino 	}
618f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
619f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
620f5b1c8a1SJohn Marino  end:
621f5b1c8a1SJohn Marino 	BIO_free(in);
622f5b1c8a1SJohn Marino 	return (ret);
623f5b1c8a1SJohn Marino }
624f5b1c8a1SJohn Marino 
625f5b1c8a1SJohn Marino int
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const unsigned char * d,long len)626f5b1c8a1SJohn Marino SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d,
627f5b1c8a1SJohn Marino     long len)
628f5b1c8a1SJohn Marino {
629f5b1c8a1SJohn Marino 	int ret;
630f5b1c8a1SJohn Marino 	EVP_PKEY *pkey;
631f5b1c8a1SJohn Marino 
63272c33676SMaxim Ag 	if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) {
63372c33676SMaxim Ag 		SSLerrorx(ERR_R_ASN1_LIB);
634f5b1c8a1SJohn Marino 		return (0);
635f5b1c8a1SJohn Marino 	}
636f5b1c8a1SJohn Marino 
637f5b1c8a1SJohn Marino 	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
638f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
639f5b1c8a1SJohn Marino 	return (ret);
640f5b1c8a1SJohn Marino }
641f5b1c8a1SJohn Marino 
642f5b1c8a1SJohn Marino 
643f5b1c8a1SJohn Marino /*
644f5b1c8a1SJohn Marino  * Read a bio that contains our certificate in "PEM" format,
645f5b1c8a1SJohn Marino  * possibly followed by a sequence of CA certificates that should be
646f5b1c8a1SJohn Marino  * sent to the peer in the Certificate message.
647f5b1c8a1SJohn Marino  */
648f5b1c8a1SJohn Marino static int
ssl_use_certificate_chain_bio(SSL_CTX * ctx,SSL * ssl,BIO * in)649*de0e0e4dSAntonio Huete Jimenez ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in)
650f5b1c8a1SJohn Marino {
651*de0e0e4dSAntonio Huete Jimenez 	pem_password_cb *passwd_cb;
652*de0e0e4dSAntonio Huete Jimenez 	void *passwd_arg;
65372c33676SMaxim Ag 	X509 *ca, *x = NULL;
654f5b1c8a1SJohn Marino 	unsigned long err;
65572c33676SMaxim Ag 	int ret = 0;
656f5b1c8a1SJohn Marino 
657*de0e0e4dSAntonio Huete Jimenez 	if (!ssl_get_password_cb_and_arg(ctx, ssl, &passwd_cb, &passwd_arg))
658*de0e0e4dSAntonio Huete Jimenez 		goto err;
659*de0e0e4dSAntonio Huete Jimenez 
660*de0e0e4dSAntonio Huete Jimenez 	if ((x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_arg)) ==
661*de0e0e4dSAntonio Huete Jimenez 	    NULL) {
66272c33676SMaxim Ag 		SSLerrorx(ERR_R_PEM_LIB);
66372c33676SMaxim Ag 		goto err;
664f5b1c8a1SJohn Marino 	}
665f5b1c8a1SJohn Marino 
666*de0e0e4dSAntonio Huete Jimenez 	if (!ssl_set_cert(ctx, ssl, x))
66772c33676SMaxim Ag 		goto err;
66872c33676SMaxim Ag 
669*de0e0e4dSAntonio Huete Jimenez 	if (!ssl_cert_set0_chain(ctx, ssl, NULL))
67072c33676SMaxim Ag 		goto err;
67172c33676SMaxim Ag 
67272c33676SMaxim Ag 	/* Process any additional CA certificates. */
673*de0e0e4dSAntonio Huete Jimenez 	while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_arg)) !=
674*de0e0e4dSAntonio Huete Jimenez 	    NULL) {
675*de0e0e4dSAntonio Huete Jimenez 		if (!ssl_cert_add0_chain_cert(ctx, ssl, ca)) {
676f5b1c8a1SJohn Marino 			X509_free(ca);
67772c33676SMaxim Ag 			goto err;
678f5b1c8a1SJohn Marino 		}
679f5b1c8a1SJohn Marino 	}
680f5b1c8a1SJohn Marino 
681f5b1c8a1SJohn Marino 	/* When the while loop ends, it's usually just EOF. */
682f5b1c8a1SJohn Marino 	err = ERR_peek_last_error();
683f5b1c8a1SJohn Marino 	if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
68472c33676SMaxim Ag 	    ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
685f5b1c8a1SJohn Marino 		ERR_clear_error();
68672c33676SMaxim Ag 		ret = 1;
687f5b1c8a1SJohn Marino 	}
688f5b1c8a1SJohn Marino 
68972c33676SMaxim Ag  err:
690f5b1c8a1SJohn Marino 	X509_free(x);
69172c33676SMaxim Ag 
692f5b1c8a1SJohn Marino 	return (ret);
693f5b1c8a1SJohn Marino }
694f5b1c8a1SJohn Marino 
695f5b1c8a1SJohn Marino int
ssl_use_certificate_chain_file(SSL_CTX * ctx,SSL * ssl,const char * file)696*de0e0e4dSAntonio Huete Jimenez ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
697f5b1c8a1SJohn Marino {
698f5b1c8a1SJohn Marino 	BIO *in;
699f5b1c8a1SJohn Marino 	int ret = 0;
700f5b1c8a1SJohn Marino 
701*de0e0e4dSAntonio Huete Jimenez 	in = BIO_new(BIO_s_file());
702f5b1c8a1SJohn Marino 	if (in == NULL) {
70372c33676SMaxim Ag 		SSLerrorx(ERR_R_BUF_LIB);
704f5b1c8a1SJohn Marino 		goto end;
705f5b1c8a1SJohn Marino 	}
706f5b1c8a1SJohn Marino 
707f5b1c8a1SJohn Marino 	if (BIO_read_filename(in, file) <= 0) {
70872c33676SMaxim Ag 		SSLerrorx(ERR_R_SYS_LIB);
709f5b1c8a1SJohn Marino 		goto end;
710f5b1c8a1SJohn Marino 	}
711f5b1c8a1SJohn Marino 
712*de0e0e4dSAntonio Huete Jimenez 	ret = ssl_use_certificate_chain_bio(ctx, ssl, in);
713f5b1c8a1SJohn Marino 
714f5b1c8a1SJohn Marino  end:
715f5b1c8a1SJohn Marino 	BIO_free(in);
716f5b1c8a1SJohn Marino 	return (ret);
717f5b1c8a1SJohn Marino }
718f5b1c8a1SJohn Marino 
719f5b1c8a1SJohn Marino int
SSL_CTX_use_certificate_chain_file(SSL_CTX * ctx,const char * file)720*de0e0e4dSAntonio Huete Jimenez SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
721*de0e0e4dSAntonio Huete Jimenez {
722*de0e0e4dSAntonio Huete Jimenez 	return ssl_use_certificate_chain_file(ctx, NULL, file);
723*de0e0e4dSAntonio Huete Jimenez }
724*de0e0e4dSAntonio Huete Jimenez 
725*de0e0e4dSAntonio Huete Jimenez int
SSL_use_certificate_chain_file(SSL * ssl,const char * file)726*de0e0e4dSAntonio Huete Jimenez SSL_use_certificate_chain_file(SSL *ssl, const char *file)
727*de0e0e4dSAntonio Huete Jimenez {
728*de0e0e4dSAntonio Huete Jimenez 	return ssl_use_certificate_chain_file(NULL, ssl, file);
729*de0e0e4dSAntonio Huete Jimenez }
730*de0e0e4dSAntonio Huete Jimenez 
731*de0e0e4dSAntonio Huete Jimenez int
SSL_CTX_use_certificate_chain_mem(SSL_CTX * ctx,void * buf,int len)732f5b1c8a1SJohn Marino SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len)
733f5b1c8a1SJohn Marino {
734f5b1c8a1SJohn Marino 	BIO *in;
735f5b1c8a1SJohn Marino 	int ret = 0;
736f5b1c8a1SJohn Marino 
737f5b1c8a1SJohn Marino 	in = BIO_new_mem_buf(buf, len);
738f5b1c8a1SJohn Marino 	if (in == NULL) {
73972c33676SMaxim Ag 		SSLerrorx(ERR_R_BUF_LIB);
740f5b1c8a1SJohn Marino 		goto end;
741f5b1c8a1SJohn Marino 	}
742f5b1c8a1SJohn Marino 
743*de0e0e4dSAntonio Huete Jimenez 	ret = ssl_use_certificate_chain_bio(ctx, NULL, in);
744f5b1c8a1SJohn Marino 
745f5b1c8a1SJohn Marino  end:
746f5b1c8a1SJohn Marino 	BIO_free(in);
747f5b1c8a1SJohn Marino 	return (ret);
748f5b1c8a1SJohn Marino }
749