xref: /openbsd-src/lib/libssl/ssl_rsa.c (revision 6565de7c7937feaa013464f37c08e9d39ba6026c)
1*6565de7cStb /* $OpenBSD: ssl_rsa.c,v 1.51 2023/12/30 06:25:56 tb Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
585b37fcf3Sryker 
595b37fcf3Sryker #include <stdio.h>
60c5899dbcSjsing 
61913ec974Sbeck #include <openssl/bio.h>
62913ec974Sbeck #include <openssl/evp.h>
63c5899dbcSjsing #include <openssl/objects.h>
64913ec974Sbeck #include <openssl/pem.h>
65c5899dbcSjsing #include <openssl/x509.h>
665b37fcf3Sryker 
67c9675a23Stb #include "ssl_local.h"
6810e340b2Sjsing 
69ba90dbc1Stb static int ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl,
70ba90dbc1Stb     pem_password_cb **passwd_cb, void **passwd_arg);
7196697e90Stb static int ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x509);
7296697e90Stb static int ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey);
739c400454Stb static int ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in);
749c400454Stb static int ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl,
759c400454Stb     const char *file);
765e89dc0dSreyk 
7735fb0677Sjsing int
SSL_use_certificate(SSL * ssl,X509 * x)7835fb0677Sjsing SSL_use_certificate(SSL *ssl, X509 *x)
795b37fcf3Sryker {
8035fb0677Sjsing 	if (x == NULL) {
81c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
825b37fcf3Sryker 		return (0);
835b37fcf3Sryker 	}
8496697e90Stb 	return ssl_set_cert(NULL, ssl, x);
855b37fcf3Sryker }
8671e04849Sbeck LSSL_ALIAS(SSL_use_certificate);
875b37fcf3Sryker 
8835fb0677Sjsing int
SSL_use_certificate_file(SSL * ssl,const char * file,int type)8935fb0677Sjsing SSL_use_certificate_file(SSL *ssl, const char *file, int type)
905b37fcf3Sryker {
915b37fcf3Sryker 	int j;
925b37fcf3Sryker 	BIO *in;
935b37fcf3Sryker 	int ret = 0;
945b37fcf3Sryker 	X509 *x = NULL;
955b37fcf3Sryker 
96590ebd80Stb 	in = BIO_new(BIO_s_file());
9735fb0677Sjsing 	if (in == NULL) {
98c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_BUF_LIB);
995b37fcf3Sryker 		goto end;
1005b37fcf3Sryker 	}
1015b37fcf3Sryker 
10235fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
103c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_SYS_LIB);
1045b37fcf3Sryker 		goto end;
1055b37fcf3Sryker 	}
10635fb0677Sjsing 	if (type == SSL_FILETYPE_ASN1) {
1075b37fcf3Sryker 		j = ERR_R_ASN1_LIB;
1085b37fcf3Sryker 		x = d2i_X509_bio(in, NULL);
10935fb0677Sjsing 	} else if (type == SSL_FILETYPE_PEM) {
1105b37fcf3Sryker 		j = ERR_R_PEM_LIB;
111790a986dSguenther 		x = PEM_read_bio_X509(in, NULL,
112c420d358Sbeck 		    ssl->ctx->default_passwd_callback,
113c420d358Sbeck 		    ssl->ctx->default_passwd_callback_userdata);
11435fb0677Sjsing 	} else {
115c9d7abb7Sbeck 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
1165b37fcf3Sryker 		goto end;
1175b37fcf3Sryker 	}
1185b37fcf3Sryker 
11935fb0677Sjsing 	if (x == NULL) {
120c9d7abb7Sbeck 		SSLerror(ssl, j);
1215b37fcf3Sryker 		goto end;
1225b37fcf3Sryker 	}
1235b37fcf3Sryker 
1245b37fcf3Sryker 	ret = SSL_use_certificate(ssl, x);
1255b37fcf3Sryker  end:
12635fb0677Sjsing 	X509_free(x);
12735fb0677Sjsing 	BIO_free(in);
1285b37fcf3Sryker 	return (ret);
1295b37fcf3Sryker }
13071e04849Sbeck LSSL_ALIAS(SSL_use_certificate_file);
1315b37fcf3Sryker 
13235fb0677Sjsing int
SSL_use_certificate_ASN1(SSL * ssl,const unsigned char * d,int len)13335fb0677Sjsing SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
1345b37fcf3Sryker {
1355b37fcf3Sryker 	X509 *x;
1365b37fcf3Sryker 	int ret;
1375b37fcf3Sryker 
1385b37fcf3Sryker 	x = d2i_X509(NULL, &d, (long)len);
13935fb0677Sjsing 	if (x == NULL) {
140c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_ASN1_LIB);
1415b37fcf3Sryker 		return (0);
1425b37fcf3Sryker 	}
1435b37fcf3Sryker 
1445b37fcf3Sryker 	ret = SSL_use_certificate(ssl, x);
1455b37fcf3Sryker 	X509_free(x);
1465b37fcf3Sryker 	return (ret);
1475b37fcf3Sryker }
14871e04849Sbeck LSSL_ALIAS(SSL_use_certificate_ASN1);
1495b37fcf3Sryker 
15035fb0677Sjsing int
SSL_use_RSAPrivateKey(SSL * ssl,RSA * rsa)15135fb0677Sjsing SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
1525b37fcf3Sryker {
153*6565de7cStb 	EVP_PKEY *pkey = NULL;
154*6565de7cStb 	int ret = 0;
1555b37fcf3Sryker 
15635fb0677Sjsing 	if (rsa == NULL) {
157c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
158*6565de7cStb 		goto err;
1595b37fcf3Sryker 	}
16035fb0677Sjsing 	if ((pkey = EVP_PKEY_new()) == NULL) {
161c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_EVP_LIB);
162*6565de7cStb 		goto err;
1635b37fcf3Sryker 	}
164*6565de7cStb 	if (!EVP_PKEY_set1_RSA(pkey, rsa))
165*6565de7cStb 		goto err;
166*6565de7cStb 	if (!ssl_set_pkey(NULL, ssl, pkey))
167*6565de7cStb 		goto err;
1685b37fcf3Sryker 
169*6565de7cStb 	ret = 1;
1705b37fcf3Sryker 
171*6565de7cStb  err:
1725b37fcf3Sryker 	EVP_PKEY_free(pkey);
173*6565de7cStb 
174*6565de7cStb 	return ret;
1755b37fcf3Sryker }
17671e04849Sbeck LSSL_ALIAS(SSL_use_RSAPrivateKey);
1775b37fcf3Sryker 
17835fb0677Sjsing static int
ssl_set_pkey(SSL_CTX * ctx,SSL * ssl,EVP_PKEY * pkey)17996697e90Stb ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey)
1805b37fcf3Sryker {
18196697e90Stb 	SSL_CERT *c;
1824fcf65c5Sdjm 	int i;
1835b37fcf3Sryker 
184e7fd08e8Sjsing 	i = ssl_cert_type(pkey);
18535fb0677Sjsing 	if (i < 0) {
186c9d7abb7Sbeck 		SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE);
1875b37fcf3Sryker 		return (0);
1885b37fcf3Sryker 	}
1895b37fcf3Sryker 
19096697e90Stb 	if ((c = ssl_get0_cert(ctx, ssl)) == NULL)
19196697e90Stb 		return (0);
19296697e90Stb 
19335fb0677Sjsing 	if (c->pkeys[i].x509 != NULL) {
194913ec974Sbeck 		EVP_PKEY *pktmp;
1955b39a737Stb 
1965b39a737Stb 		if ((pktmp = X509_get0_pubkey(c->pkeys[i].x509)) == NULL)
1975b39a737Stb 			return 0;
1985b39a737Stb 
1995b39a737Stb 		/*
2005b39a737Stb 		 * Callers of EVP_PKEY_copy_parameters() can't distinguish
2015b39a737Stb 		 * errors from the absence of a param_copy() method. So
2025b39a737Stb 		 * pretend it can never fail.
2035b39a737Stb 		 */
204b17cb24aStb 		EVP_PKEY_copy_parameters(pktmp, pkey);
2055b39a737Stb 
206913ec974Sbeck 		ERR_clear_error();
207913ec974Sbeck 
208790a986dSguenther 		/*
209790a986dSguenther 		 * Don't check the public/private key, this is mostly
210790a986dSguenther 		 * for smart cards.
211790a986dSguenther 		 */
212f1ba087aStb 		if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA ||
213f1ba087aStb 		    !(RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK)) {
21435fb0677Sjsing 			if (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
2155b37fcf3Sryker 				X509_free(c->pkeys[i].x509);
2165b37fcf3Sryker 				c->pkeys[i].x509 = NULL;
2174fcf65c5Sdjm 				return 0;
2184fcf65c5Sdjm 			}
2195b37fcf3Sryker 		}
220f1ba087aStb 	}
2215b37fcf3Sryker 
2225b37fcf3Sryker 	EVP_PKEY_free(c->pkeys[i].privatekey);
223f1ba087aStb 	EVP_PKEY_up_ref(pkey);
2245b37fcf3Sryker 	c->pkeys[i].privatekey = pkey;
2255b37fcf3Sryker 	c->key = &(c->pkeys[i]);
2265b37fcf3Sryker 
2275b37fcf3Sryker 	c->valid = 0;
2285b39a737Stb 	return 1;
2295b37fcf3Sryker }
2305b37fcf3Sryker 
23135fb0677Sjsing int
SSL_use_RSAPrivateKey_file(SSL * ssl,const char * file,int type)23235fb0677Sjsing SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
2335b37fcf3Sryker {
2345b37fcf3Sryker 	int j, ret = 0;
2355b37fcf3Sryker 	BIO *in;
2365b37fcf3Sryker 	RSA *rsa = NULL;
2375b37fcf3Sryker 
238590ebd80Stb 	in = BIO_new(BIO_s_file());
23935fb0677Sjsing 	if (in == NULL) {
240c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_BUF_LIB);
2415b37fcf3Sryker 		goto end;
2425b37fcf3Sryker 	}
2435b37fcf3Sryker 
24435fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
245c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_SYS_LIB);
2465b37fcf3Sryker 		goto end;
2475b37fcf3Sryker 	}
24835fb0677Sjsing 	if (type == SSL_FILETYPE_ASN1) {
2495b37fcf3Sryker 		j = ERR_R_ASN1_LIB;
2505b37fcf3Sryker 		rsa = d2i_RSAPrivateKey_bio(in, NULL);
25135fb0677Sjsing 	} else if (type == SSL_FILETYPE_PEM) {
2525b37fcf3Sryker 		j = ERR_R_PEM_LIB;
2535b37fcf3Sryker 		rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
254c420d358Sbeck 		    ssl->ctx->default_passwd_callback,
255c420d358Sbeck 		    ssl->ctx->default_passwd_callback_userdata);
25635fb0677Sjsing 	} else {
257c9d7abb7Sbeck 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
2585b37fcf3Sryker 		goto end;
2595b37fcf3Sryker 	}
26035fb0677Sjsing 	if (rsa == NULL) {
261c9d7abb7Sbeck 		SSLerror(ssl, j);
2625b37fcf3Sryker 		goto end;
2635b37fcf3Sryker 	}
2645b37fcf3Sryker 	ret = SSL_use_RSAPrivateKey(ssl, rsa);
2655b37fcf3Sryker 	RSA_free(rsa);
2665b37fcf3Sryker  end:
26735fb0677Sjsing 	BIO_free(in);
2685b37fcf3Sryker 	return (ret);
2695b37fcf3Sryker }
27071e04849Sbeck LSSL_ALIAS(SSL_use_RSAPrivateKey_file);
2715b37fcf3Sryker 
27235fb0677Sjsing int
SSL_use_RSAPrivateKey_ASN1(SSL * ssl,const unsigned char * d,long len)2730a4fabb9Stb SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
2745b37fcf3Sryker {
2755b37fcf3Sryker 	int ret;
2765b37fcf3Sryker 	RSA *rsa;
2775b37fcf3Sryker 
2780a4fabb9Stb 	if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) {
279c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_ASN1_LIB);
2805b37fcf3Sryker 		return (0);
2815b37fcf3Sryker 	}
2825b37fcf3Sryker 
2835b37fcf3Sryker 	ret = SSL_use_RSAPrivateKey(ssl, rsa);
2845b37fcf3Sryker 	RSA_free(rsa);
2855b37fcf3Sryker 	return (ret);
2865b37fcf3Sryker }
28771e04849Sbeck LSSL_ALIAS(SSL_use_RSAPrivateKey_ASN1);
2885b37fcf3Sryker 
28935fb0677Sjsing int
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)29035fb0677Sjsing SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
2915b37fcf3Sryker {
2925b37fcf3Sryker 	int ret;
2935b37fcf3Sryker 
29435fb0677Sjsing 	if (pkey == NULL) {
295c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER);
2965b37fcf3Sryker 		return (0);
2975b37fcf3Sryker 	}
29896697e90Stb 	ret = ssl_set_pkey(NULL, ssl, pkey);
2995b37fcf3Sryker 	return (ret);
3005b37fcf3Sryker }
30171e04849Sbeck LSSL_ALIAS(SSL_use_PrivateKey);
3025b37fcf3Sryker 
30335fb0677Sjsing int
SSL_use_PrivateKey_file(SSL * ssl,const char * file,int type)30435fb0677Sjsing SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
3055b37fcf3Sryker {
3065b37fcf3Sryker 	int j, ret = 0;
3075b37fcf3Sryker 	BIO *in;
3085b37fcf3Sryker 	EVP_PKEY *pkey = NULL;
3095b37fcf3Sryker 
310590ebd80Stb 	in = BIO_new(BIO_s_file());
31135fb0677Sjsing 	if (in == NULL) {
312c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_BUF_LIB);
3135b37fcf3Sryker 		goto end;
3145b37fcf3Sryker 	}
3155b37fcf3Sryker 
31635fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
317c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_SYS_LIB);
3185b37fcf3Sryker 		goto end;
3195b37fcf3Sryker 	}
32035fb0677Sjsing 	if (type == SSL_FILETYPE_PEM) {
3215b37fcf3Sryker 		j = ERR_R_PEM_LIB;
3225b37fcf3Sryker 		pkey = PEM_read_bio_PrivateKey(in, NULL,
323c420d358Sbeck 		    ssl->ctx->default_passwd_callback,
324c420d358Sbeck 		    ssl->ctx->default_passwd_callback_userdata);
32535fb0677Sjsing 	} else if (type == SSL_FILETYPE_ASN1) {
3264fcf65c5Sdjm 		j = ERR_R_ASN1_LIB;
3274fcf65c5Sdjm 		pkey = d2i_PrivateKey_bio(in, NULL);
32835fb0677Sjsing 	} else {
329c9d7abb7Sbeck 		SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE);
3305b37fcf3Sryker 		goto end;
3315b37fcf3Sryker 	}
33235fb0677Sjsing 	if (pkey == NULL) {
333c9d7abb7Sbeck 		SSLerror(ssl, j);
3345b37fcf3Sryker 		goto end;
3355b37fcf3Sryker 	}
3365b37fcf3Sryker 	ret = SSL_use_PrivateKey(ssl, pkey);
3375b37fcf3Sryker 	EVP_PKEY_free(pkey);
3385b37fcf3Sryker  end:
33935fb0677Sjsing 	BIO_free(in);
3405b37fcf3Sryker 	return (ret);
3415b37fcf3Sryker }
34271e04849Sbeck LSSL_ALIAS(SSL_use_PrivateKey_file);
3435b37fcf3Sryker 
34435fb0677Sjsing int
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const unsigned char * d,long len)34535fb0677Sjsing SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len)
3465b37fcf3Sryker {
3475b37fcf3Sryker 	int ret;
3485b37fcf3Sryker 	EVP_PKEY *pkey;
3495b37fcf3Sryker 
3500a4fabb9Stb 	if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) {
351c9d7abb7Sbeck 		SSLerror(ssl, ERR_R_ASN1_LIB);
3525b37fcf3Sryker 		return (0);
3535b37fcf3Sryker 	}
3545b37fcf3Sryker 
3555b37fcf3Sryker 	ret = SSL_use_PrivateKey(ssl, pkey);
3565b37fcf3Sryker 	EVP_PKEY_free(pkey);
3575b37fcf3Sryker 	return (ret);
3585b37fcf3Sryker }
35971e04849Sbeck LSSL_ALIAS(SSL_use_PrivateKey_ASN1);
3605b37fcf3Sryker 
36135fb0677Sjsing int
SSL_CTX_use_certificate(SSL_CTX * ctx,X509 * x)36235fb0677Sjsing SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
3635b37fcf3Sryker {
36435fb0677Sjsing 	if (x == NULL) {
365c9d7abb7Sbeck 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
3665b37fcf3Sryker 		return (0);
3675b37fcf3Sryker 	}
36896697e90Stb 	return ssl_set_cert(ctx, NULL, x);
3695b37fcf3Sryker }
37071e04849Sbeck LSSL_ALIAS(SSL_CTX_use_certificate);
3715b37fcf3Sryker 
37235fb0677Sjsing static int
ssl_get_password_cb_and_arg(SSL_CTX * ctx,SSL * ssl,pem_password_cb ** passwd_cb,void ** passwd_arg)373ba90dbc1Stb ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl,
374ba90dbc1Stb     pem_password_cb **passwd_cb, void **passwd_arg)
375ba90dbc1Stb {
376ba90dbc1Stb 	if (ssl != NULL)
377ba90dbc1Stb 		ctx = ssl->ctx;
378ba90dbc1Stb 
379ba90dbc1Stb 	*passwd_cb = ctx->default_passwd_callback;
380ba90dbc1Stb 	*passwd_arg = ctx->default_passwd_callback_userdata;
381ba90dbc1Stb 
382ba90dbc1Stb 	return 1;
383ba90dbc1Stb }
384ba90dbc1Stb 
385ba90dbc1Stb static int
ssl_set_cert(SSL_CTX * ctx,SSL * ssl,X509 * x)38696697e90Stb ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x)
3875b37fcf3Sryker {
38896697e90Stb 	SSL_CERT *c;
3895b37fcf3Sryker 	EVP_PKEY *pkey;
39091075168Stb 	int ssl_err;
3914fcf65c5Sdjm 	int i;
3925b37fcf3Sryker 
39391075168Stb 	if (!ssl_security_cert(ctx, ssl, x, 1, &ssl_err)) {
39491075168Stb 		SSLerrorx(ssl_err);
39591075168Stb 		return (0);
39691075168Stb 	}
39791075168Stb 
39896697e90Stb 	if ((c = ssl_get0_cert(ctx, ssl)) == NULL)
39996697e90Stb 		return (0);
40096697e90Stb 
4015b37fcf3Sryker 	pkey = X509_get_pubkey(x);
40235fb0677Sjsing 	if (pkey == NULL) {
403c9d7abb7Sbeck 		SSLerrorx(SSL_R_X509_LIB);
4045b37fcf3Sryker 		return (0);
4055b37fcf3Sryker 	}
4065b37fcf3Sryker 
407e7fd08e8Sjsing 	i = ssl_cert_type(pkey);
40835fb0677Sjsing 	if (i < 0) {
409c9d7abb7Sbeck 		SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE);
410913ec974Sbeck 		EVP_PKEY_free(pkey);
4115b37fcf3Sryker 		return (0);
4125b37fcf3Sryker 	}
4135b37fcf3Sryker 
41435fb0677Sjsing 	if (c->pkeys[i].privatekey != NULL) {
415f1ba087aStb 		EVP_PKEY *priv_key = c->pkeys[i].privatekey;
416f1ba087aStb 
417f1ba087aStb 		EVP_PKEY_copy_parameters(pkey, priv_key);
418913ec974Sbeck 		ERR_clear_error();
419913ec974Sbeck 
420790a986dSguenther 		/*
421790a986dSguenther 		 * Don't check the public/private key, this is mostly
422790a986dSguenther 		 * for smart cards.
423790a986dSguenther 		 */
424f1ba087aStb 		if (EVP_PKEY_id(priv_key) != EVP_PKEY_RSA ||
425f1ba087aStb 		    !(RSA_flags(EVP_PKEY_get0_RSA(priv_key)) & RSA_METHOD_FLAG_NO_CHECK)) {
426f1ba087aStb 			if (!X509_check_private_key(x, priv_key)) {
427790a986dSguenther 				/*
428790a986dSguenther 				 * don't fail for a cert/key mismatch, just free
429f1ba087aStb 				 * current private key (when switching to a
430f1ba087aStb 				 * different cert & key, first this function
431f1ba087aStb 				 * should be used, then ssl_set_pkey.
432790a986dSguenther 				 */
4335b37fcf3Sryker 				EVP_PKEY_free(c->pkeys[i].privatekey);
4345b37fcf3Sryker 				c->pkeys[i].privatekey = NULL;
4354fcf65c5Sdjm 				ERR_clear_error();
4365b37fcf3Sryker 			}
4374fcf65c5Sdjm 		}
438f1ba087aStb 	}
4394fcf65c5Sdjm 
4404fcf65c5Sdjm 	EVP_PKEY_free(pkey);
4415b37fcf3Sryker 
4425b37fcf3Sryker 	X509_free(c->pkeys[i].x509);
443526e2352Stb 	X509_up_ref(x);
4445b37fcf3Sryker 	c->pkeys[i].x509 = x;
4455b37fcf3Sryker 	c->key = &(c->pkeys[i]);
4465b37fcf3Sryker 
4475b37fcf3Sryker 	c->valid = 0;
4485b37fcf3Sryker 	return (1);
4495b37fcf3Sryker }
4505b37fcf3Sryker 
45135fb0677Sjsing int
SSL_CTX_use_certificate_file(SSL_CTX * ctx,const char * file,int type)45235fb0677Sjsing SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
4535b37fcf3Sryker {
4545b37fcf3Sryker 	int j;
4555b37fcf3Sryker 	BIO *in;
4565b37fcf3Sryker 	int ret = 0;
4575b37fcf3Sryker 	X509 *x = NULL;
4585b37fcf3Sryker 
459590ebd80Stb 	in = BIO_new(BIO_s_file());
46035fb0677Sjsing 	if (in == NULL) {
461c9d7abb7Sbeck 		SSLerrorx(ERR_R_BUF_LIB);
4625b37fcf3Sryker 		goto end;
4635b37fcf3Sryker 	}
4645b37fcf3Sryker 
46535fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
466c9d7abb7Sbeck 		SSLerrorx(ERR_R_SYS_LIB);
4675b37fcf3Sryker 		goto end;
4685b37fcf3Sryker 	}
46935fb0677Sjsing 	if (type == SSL_FILETYPE_ASN1) {
4705b37fcf3Sryker 		j = ERR_R_ASN1_LIB;
4715b37fcf3Sryker 		x = d2i_X509_bio(in, NULL);
47235fb0677Sjsing 	} else if (type == SSL_FILETYPE_PEM) {
4735b37fcf3Sryker 		j = ERR_R_PEM_LIB;
474c420d358Sbeck 		x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
475c420d358Sbeck 		    ctx->default_passwd_callback_userdata);
47635fb0677Sjsing 	} else {
477c9d7abb7Sbeck 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
4785b37fcf3Sryker 		goto end;
4795b37fcf3Sryker 	}
4805b37fcf3Sryker 
48135fb0677Sjsing 	if (x == NULL) {
482c9d7abb7Sbeck 		SSLerrorx(j);
4835b37fcf3Sryker 		goto end;
4845b37fcf3Sryker 	}
4855b37fcf3Sryker 
4865b37fcf3Sryker 	ret = SSL_CTX_use_certificate(ctx, x);
4875b37fcf3Sryker  end:
48835fb0677Sjsing 	X509_free(x);
48935fb0677Sjsing 	BIO_free(in);
4905b37fcf3Sryker 	return (ret);
4915b37fcf3Sryker }
49271e04849Sbeck LSSL_ALIAS(SSL_CTX_use_certificate_file);
4935b37fcf3Sryker 
49435fb0677Sjsing int
SSL_CTX_use_certificate_ASN1(SSL_CTX * ctx,int len,const unsigned char * d)49535fb0677Sjsing SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
4965b37fcf3Sryker {
4975b37fcf3Sryker 	X509 *x;
4985b37fcf3Sryker 	int ret;
4995b37fcf3Sryker 
5005b37fcf3Sryker 	x = d2i_X509(NULL, &d, (long)len);
50135fb0677Sjsing 	if (x == NULL) {
502c9d7abb7Sbeck 		SSLerrorx(ERR_R_ASN1_LIB);
5035b37fcf3Sryker 		return (0);
5045b37fcf3Sryker 	}
5055b37fcf3Sryker 
5065b37fcf3Sryker 	ret = SSL_CTX_use_certificate(ctx, x);
5075b37fcf3Sryker 	X509_free(x);
5085b37fcf3Sryker 	return (ret);
5095b37fcf3Sryker }
51071e04849Sbeck LSSL_ALIAS(SSL_CTX_use_certificate_ASN1);
5115b37fcf3Sryker 
51235fb0677Sjsing int
SSL_CTX_use_RSAPrivateKey(SSL_CTX * ctx,RSA * rsa)51335fb0677Sjsing SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
5145b37fcf3Sryker {
515*6565de7cStb 	EVP_PKEY *pkey = NULL;
516*6565de7cStb 	int ret = 0;
5175b37fcf3Sryker 
51835fb0677Sjsing 	if (rsa == NULL) {
519c9d7abb7Sbeck 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
520*6565de7cStb 		goto err;
5215b37fcf3Sryker 	}
52235fb0677Sjsing 	if ((pkey = EVP_PKEY_new()) == NULL) {
523c9d7abb7Sbeck 		SSLerrorx(ERR_R_EVP_LIB);
524*6565de7cStb 		goto err;
5255b37fcf3Sryker 	}
526*6565de7cStb 	if (!EVP_PKEY_set1_RSA(pkey, rsa))
527*6565de7cStb 		goto err;
528*6565de7cStb 	if (!ssl_set_pkey(ctx, NULL, pkey))
529*6565de7cStb 		goto err;
5305b37fcf3Sryker 
531*6565de7cStb 	ret = 1;
5325b37fcf3Sryker 
533*6565de7cStb  err:
5345b37fcf3Sryker 	EVP_PKEY_free(pkey);
535*6565de7cStb 
536*6565de7cStb 	return ret;
5375b37fcf3Sryker }
53871e04849Sbeck LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey);
5395b37fcf3Sryker 
54035fb0677Sjsing int
SSL_CTX_use_RSAPrivateKey_file(SSL_CTX * ctx,const char * file,int type)54135fb0677Sjsing SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
5425b37fcf3Sryker {
5435b37fcf3Sryker 	int j, ret = 0;
5445b37fcf3Sryker 	BIO *in;
5455b37fcf3Sryker 	RSA *rsa = NULL;
5465b37fcf3Sryker 
547590ebd80Stb 	in = BIO_new(BIO_s_file());
54835fb0677Sjsing 	if (in == NULL) {
549c9d7abb7Sbeck 		SSLerrorx(ERR_R_BUF_LIB);
5505b37fcf3Sryker 		goto end;
5515b37fcf3Sryker 	}
5525b37fcf3Sryker 
55335fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
554c9d7abb7Sbeck 		SSLerrorx(ERR_R_SYS_LIB);
5555b37fcf3Sryker 		goto end;
5565b37fcf3Sryker 	}
55735fb0677Sjsing 	if (type == SSL_FILETYPE_ASN1) {
5585b37fcf3Sryker 		j = ERR_R_ASN1_LIB;
5595b37fcf3Sryker 		rsa = d2i_RSAPrivateKey_bio(in, NULL);
56035fb0677Sjsing 	} else if (type == SSL_FILETYPE_PEM) {
5615b37fcf3Sryker 		j = ERR_R_PEM_LIB;
5625b37fcf3Sryker 		rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
563c420d358Sbeck 		    ctx->default_passwd_callback,
564c420d358Sbeck 		    ctx->default_passwd_callback_userdata);
56535fb0677Sjsing 	} else {
566c9d7abb7Sbeck 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
5675b37fcf3Sryker 		goto end;
5685b37fcf3Sryker 	}
56935fb0677Sjsing 	if (rsa == NULL) {
570c9d7abb7Sbeck 		SSLerrorx(j);
5715b37fcf3Sryker 		goto end;
5725b37fcf3Sryker 	}
5735b37fcf3Sryker 	ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
5745b37fcf3Sryker 	RSA_free(rsa);
5755b37fcf3Sryker  end:
57635fb0677Sjsing 	BIO_free(in);
5775b37fcf3Sryker 	return (ret);
5785b37fcf3Sryker }
57971e04849Sbeck LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey_file);
5805b37fcf3Sryker 
58135fb0677Sjsing int
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const unsigned char * d,long len)58235fb0677Sjsing SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
5835b37fcf3Sryker {
5845b37fcf3Sryker 	int ret;
5855b37fcf3Sryker 	RSA *rsa;
5865b37fcf3Sryker 
5870a4fabb9Stb 	if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) {
588c9d7abb7Sbeck 		SSLerrorx(ERR_R_ASN1_LIB);
5895b37fcf3Sryker 		return (0);
5905b37fcf3Sryker 	}
5915b37fcf3Sryker 
5925b37fcf3Sryker 	ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
5935b37fcf3Sryker 	RSA_free(rsa);
5945b37fcf3Sryker 	return (ret);
5955b37fcf3Sryker }
59671e04849Sbeck LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey_ASN1);
5975b37fcf3Sryker 
59835fb0677Sjsing int
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)59935fb0677Sjsing SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
6005b37fcf3Sryker {
60135fb0677Sjsing 	if (pkey == NULL) {
602c9d7abb7Sbeck 		SSLerrorx(ERR_R_PASSED_NULL_PARAMETER);
6035b37fcf3Sryker 		return (0);
6045b37fcf3Sryker 	}
60596697e90Stb 	return ssl_set_pkey(ctx, NULL, pkey);
6065b37fcf3Sryker }
60771e04849Sbeck LSSL_ALIAS(SSL_CTX_use_PrivateKey);
6085b37fcf3Sryker 
60935fb0677Sjsing int
SSL_CTX_use_PrivateKey_file(SSL_CTX * ctx,const char * file,int type)61035fb0677Sjsing SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
6115b37fcf3Sryker {
6125b37fcf3Sryker 	int j, ret = 0;
6135b37fcf3Sryker 	BIO *in;
6145b37fcf3Sryker 	EVP_PKEY *pkey = NULL;
6155b37fcf3Sryker 
616590ebd80Stb 	in = BIO_new(BIO_s_file());
61735fb0677Sjsing 	if (in == NULL) {
618c9d7abb7Sbeck 		SSLerrorx(ERR_R_BUF_LIB);
6195b37fcf3Sryker 		goto end;
6205b37fcf3Sryker 	}
6215b37fcf3Sryker 
62235fb0677Sjsing 	if (BIO_read_filename(in, file) <= 0) {
623c9d7abb7Sbeck 		SSLerrorx(ERR_R_SYS_LIB);
6245b37fcf3Sryker 		goto end;
6255b37fcf3Sryker 	}
62635fb0677Sjsing 	if (type == SSL_FILETYPE_PEM) {
6275b37fcf3Sryker 		j = ERR_R_PEM_LIB;
6285b37fcf3Sryker 		pkey = PEM_read_bio_PrivateKey(in, NULL,
629c420d358Sbeck 		    ctx->default_passwd_callback,
630c420d358Sbeck 		    ctx->default_passwd_callback_userdata);
63135fb0677Sjsing 	} else if (type == SSL_FILETYPE_ASN1) {
6324fcf65c5Sdjm 		j = ERR_R_ASN1_LIB;
6334fcf65c5Sdjm 		pkey = d2i_PrivateKey_bio(in, NULL);
63435fb0677Sjsing 	} else {
635c9d7abb7Sbeck 		SSLerrorx(SSL_R_BAD_SSL_FILETYPE);
6365b37fcf3Sryker 		goto end;
6375b37fcf3Sryker 	}
63835fb0677Sjsing 	if (pkey == NULL) {
639c9d7abb7Sbeck 		SSLerrorx(j);
6405b37fcf3Sryker 		goto end;
6415b37fcf3Sryker 	}
6425b37fcf3Sryker 	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
6435b37fcf3Sryker 	EVP_PKEY_free(pkey);
6445b37fcf3Sryker  end:
64535fb0677Sjsing 	BIO_free(in);
6465b37fcf3Sryker 	return (ret);
6475b37fcf3Sryker }
64871e04849Sbeck LSSL_ALIAS(SSL_CTX_use_PrivateKey_file);
6495b37fcf3Sryker 
65035fb0677Sjsing int
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const unsigned char * d,long len)65135fb0677Sjsing SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d,
652913ec974Sbeck     long len)
6535b37fcf3Sryker {
6545b37fcf3Sryker 	int ret;
6555b37fcf3Sryker 	EVP_PKEY *pkey;
6565b37fcf3Sryker 
6570a4fabb9Stb 	if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) {
658c9d7abb7Sbeck 		SSLerrorx(ERR_R_ASN1_LIB);
6595b37fcf3Sryker 		return (0);
6605b37fcf3Sryker 	}
6615b37fcf3Sryker 
6625b37fcf3Sryker 	ret = SSL_CTX_use_PrivateKey(ctx, pkey);
6635b37fcf3Sryker 	EVP_PKEY_free(pkey);
6645b37fcf3Sryker 	return (ret);
6655b37fcf3Sryker }
66671e04849Sbeck LSSL_ALIAS(SSL_CTX_use_PrivateKey_ASN1);
6675b37fcf3Sryker 
6685b37fcf3Sryker 
669790a986dSguenther /*
6705e89dc0dSreyk  * Read a bio that contains our certificate in "PEM" format,
671913ec974Sbeck  * possibly followed by a sequence of CA certificates that should be
672913ec974Sbeck  * sent to the peer in the Certificate message.
673913ec974Sbeck  */
6745e89dc0dSreyk static int
ssl_use_certificate_chain_bio(SSL_CTX * ctx,SSL * ssl,BIO * in)6759c400454Stb ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in)
676913ec974Sbeck {
677ba90dbc1Stb 	pem_password_cb *passwd_cb;
678ba90dbc1Stb 	void *passwd_arg;
6792e83ec4fSjsing 	X509 *ca, *x = NULL;
6802e83ec4fSjsing 	unsigned long err;
681913ec974Sbeck 	int ret = 0;
682913ec974Sbeck 
683ba90dbc1Stb 	if (!ssl_get_password_cb_and_arg(ctx, ssl, &passwd_cb, &passwd_arg))
684ba90dbc1Stb 		goto err;
685ba90dbc1Stb 
6862be1b120Stb 	if ((x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_arg)) ==
6872be1b120Stb 	    NULL) {
688c9d7abb7Sbeck 		SSLerrorx(ERR_R_PEM_LIB);
6892e83ec4fSjsing 		goto err;
690913ec974Sbeck 	}
691913ec974Sbeck 
69296697e90Stb 	if (!ssl_set_cert(ctx, ssl, x))
6932e83ec4fSjsing 		goto err;
69497222eddSmiod 
6955dbcc7f0Stb 	if (!ssl_cert_set0_chain(ctx, ssl, NULL))
6962e83ec4fSjsing 		goto err;
697913ec974Sbeck 
6982e83ec4fSjsing 	/* Process any additional CA certificates. */
6992be1b120Stb 	while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_arg)) !=
7002be1b120Stb 	    NULL) {
701dc2a950bStb 		if (!ssl_cert_add0_chain_cert(ctx, ssl, ca)) {
702913ec974Sbeck 			X509_free(ca);
7032e83ec4fSjsing 			goto err;
704913ec974Sbeck 		}
705913ec974Sbeck 	}
706790a986dSguenther 
707913ec974Sbeck 	/* When the while loop ends, it's usually just EOF. */
708da347917Sbeck 	err = ERR_peek_last_error();
709790a986dSguenther 	if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
7102e83ec4fSjsing 	    ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
71140d8aef3Sdjm 		ERR_clear_error();
7122e83ec4fSjsing 		ret = 1;
713913ec974Sbeck 	}
714913ec974Sbeck 
7152e83ec4fSjsing  err:
71635fb0677Sjsing 	X509_free(x);
7172e83ec4fSjsing 
7185e89dc0dSreyk 	return (ret);
7195e89dc0dSreyk }
7205e89dc0dSreyk 
7215e89dc0dSreyk int
ssl_use_certificate_chain_file(SSL_CTX * ctx,SSL * ssl,const char * file)7229c400454Stb ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
7235e89dc0dSreyk {
7245e89dc0dSreyk 	BIO *in;
7255e89dc0dSreyk 	int ret = 0;
7265e89dc0dSreyk 
727590ebd80Stb 	in = BIO_new(BIO_s_file());
7285e89dc0dSreyk 	if (in == NULL) {
729c9d7abb7Sbeck 		SSLerrorx(ERR_R_BUF_LIB);
7305e89dc0dSreyk 		goto end;
7315e89dc0dSreyk 	}
7325e89dc0dSreyk 
7335e89dc0dSreyk 	if (BIO_read_filename(in, file) <= 0) {
734c9d7abb7Sbeck 		SSLerrorx(ERR_R_SYS_LIB);
7355e89dc0dSreyk 		goto end;
7365e89dc0dSreyk 	}
7375e89dc0dSreyk 
7389c400454Stb 	ret = ssl_use_certificate_chain_bio(ctx, ssl, in);
7395e89dc0dSreyk 
7405e89dc0dSreyk  end:
7415e89dc0dSreyk 	BIO_free(in);
7425e89dc0dSreyk 	return (ret);
7435e89dc0dSreyk }
7445e89dc0dSreyk 
7455e89dc0dSreyk int
SSL_CTX_use_certificate_chain_file(SSL_CTX * ctx,const char * file)7462be1b120Stb SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
7472be1b120Stb {
7489c400454Stb 	return ssl_use_certificate_chain_file(ctx, NULL, file);
7492be1b120Stb }
75071e04849Sbeck LSSL_ALIAS(SSL_CTX_use_certificate_chain_file);
7512be1b120Stb 
7522be1b120Stb int
SSL_use_certificate_chain_file(SSL * ssl,const char * file)7532be1b120Stb SSL_use_certificate_chain_file(SSL *ssl, const char *file)
7542be1b120Stb {
7559c400454Stb 	return ssl_use_certificate_chain_file(NULL, ssl, file);
7562be1b120Stb }
75771e04849Sbeck LSSL_ALIAS(SSL_use_certificate_chain_file);
7582be1b120Stb 
7592be1b120Stb int
SSL_CTX_use_certificate_chain_mem(SSL_CTX * ctx,void * buf,int len)760642f72f1Sreyk SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len)
7615e89dc0dSreyk {
7625e89dc0dSreyk 	BIO *in;
7635e89dc0dSreyk 	int ret = 0;
7645e89dc0dSreyk 
7655e89dc0dSreyk 	in = BIO_new_mem_buf(buf, len);
7665e89dc0dSreyk 	if (in == NULL) {
767c9d7abb7Sbeck 		SSLerrorx(ERR_R_BUF_LIB);
7685e89dc0dSreyk 		goto end;
7695e89dc0dSreyk 	}
7705e89dc0dSreyk 
7719c400454Stb 	ret = ssl_use_certificate_chain_bio(ctx, NULL, in);
7725e89dc0dSreyk 
7735e89dc0dSreyk  end:
77435fb0677Sjsing 	BIO_free(in);
775913ec974Sbeck 	return (ret);
776913ec974Sbeck }
77771e04849Sbeck LSSL_ALIAS(SSL_CTX_use_certificate_chain_mem);
778