xref: /openbsd/lib/libtls/tls_keypair.c (revision 7a756d37)
1*7a756d37Sjoshua /* $OpenBSD: tls_keypair.c,v 1.9 2024/03/26 06:24:52 joshua Exp $ */
2bb4cb1b0Sjsing /*
3bb4cb1b0Sjsing  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4bb4cb1b0Sjsing  *
5bb4cb1b0Sjsing  * Permission to use, copy, modify, and distribute this software for any
6bb4cb1b0Sjsing  * purpose with or without fee is hereby granted, provided that the above
7bb4cb1b0Sjsing  * copyright notice and this permission notice appear in all copies.
8bb4cb1b0Sjsing  *
9bb4cb1b0Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10bb4cb1b0Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11bb4cb1b0Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12bb4cb1b0Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13bb4cb1b0Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14bb4cb1b0Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15bb4cb1b0Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16bb4cb1b0Sjsing  */
17bb4cb1b0Sjsing 
18bb4cb1b0Sjsing #include <openssl/bio.h>
19bb4cb1b0Sjsing #include <openssl/err.h>
20bb4cb1b0Sjsing #include <openssl/pem.h>
21bb4cb1b0Sjsing 
22bb4cb1b0Sjsing #include <tls.h>
23bb4cb1b0Sjsing 
24bb4cb1b0Sjsing #include "tls_internal.h"
25bb4cb1b0Sjsing 
26bb4cb1b0Sjsing struct tls_keypair *
tls_keypair_new(void)27bb4cb1b0Sjsing tls_keypair_new(void)
28bb4cb1b0Sjsing {
29bb4cb1b0Sjsing 	return calloc(1, sizeof(struct tls_keypair));
30bb4cb1b0Sjsing }
31bb4cb1b0Sjsing 
322974e8f1Sjsing static int
tls_keypair_pubkey_hash(struct tls_keypair * keypair,struct tls_error * error)332974e8f1Sjsing tls_keypair_pubkey_hash(struct tls_keypair *keypair, struct tls_error *error)
342974e8f1Sjsing {
352974e8f1Sjsing 	X509 *cert = NULL;
362974e8f1Sjsing 	int rv = -1;
372974e8f1Sjsing 
382974e8f1Sjsing 	free(keypair->pubkey_hash);
392974e8f1Sjsing 	keypair->pubkey_hash = NULL;
402974e8f1Sjsing 
412974e8f1Sjsing 	if (keypair->cert_mem == NULL) {
422974e8f1Sjsing 		rv = 0;
432974e8f1Sjsing 		goto done;
442974e8f1Sjsing 	}
452974e8f1Sjsing 
462974e8f1Sjsing 	if (tls_keypair_load_cert(keypair, error, &cert) == -1)
472974e8f1Sjsing 		goto err;
482974e8f1Sjsing 	if (tls_cert_pubkey_hash(cert, &keypair->pubkey_hash) == -1)
492974e8f1Sjsing 		goto err;
502974e8f1Sjsing 
512974e8f1Sjsing 	rv = 0;
522974e8f1Sjsing 
532974e8f1Sjsing  err:
542974e8f1Sjsing 	X509_free(cert);
552974e8f1Sjsing  done:
562974e8f1Sjsing 	return (rv);
572974e8f1Sjsing }
582974e8f1Sjsing 
59b3064b8aSjsing void
tls_keypair_clear_key(struct tls_keypair * keypair)60b3064b8aSjsing tls_keypair_clear_key(struct tls_keypair *keypair)
61b3064b8aSjsing {
62b3064b8aSjsing 	freezero(keypair->key_mem, keypair->key_len);
63b3064b8aSjsing 	keypair->key_mem = NULL;
64b3064b8aSjsing 	keypair->key_len = 0;
65b3064b8aSjsing }
66b3064b8aSjsing 
67bb4cb1b0Sjsing int
tls_keypair_set_cert_file(struct tls_keypair * keypair,struct tls_error * error,const char * cert_file)68bb4cb1b0Sjsing tls_keypair_set_cert_file(struct tls_keypair *keypair, struct tls_error *error,
69bb4cb1b0Sjsing     const char *cert_file)
70bb4cb1b0Sjsing {
712974e8f1Sjsing 	if (tls_config_load_file(error, "certificate", cert_file,
722974e8f1Sjsing 	    &keypair->cert_mem, &keypair->cert_len) == -1)
732974e8f1Sjsing 		return -1;
742974e8f1Sjsing 	return tls_keypair_pubkey_hash(keypair, error);
75bb4cb1b0Sjsing }
76bb4cb1b0Sjsing 
77bb4cb1b0Sjsing int
tls_keypair_set_cert_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * cert,size_t len)782974e8f1Sjsing tls_keypair_set_cert_mem(struct tls_keypair *keypair, struct tls_error *error,
792974e8f1Sjsing     const uint8_t *cert, size_t len)
80bb4cb1b0Sjsing {
812974e8f1Sjsing 	if (tls_set_mem(&keypair->cert_mem, &keypair->cert_len, cert, len) == -1)
822974e8f1Sjsing 		return -1;
832974e8f1Sjsing 	return tls_keypair_pubkey_hash(keypair, error);
84bb4cb1b0Sjsing }
85bb4cb1b0Sjsing 
86bb4cb1b0Sjsing int
tls_keypair_set_key_file(struct tls_keypair * keypair,struct tls_error * error,const char * key_file)87bb4cb1b0Sjsing tls_keypair_set_key_file(struct tls_keypair *keypair, struct tls_error *error,
88bb4cb1b0Sjsing     const char *key_file)
89bb4cb1b0Sjsing {
90bb4cb1b0Sjsing 	tls_keypair_clear_key(keypair);
91bb4cb1b0Sjsing 	return tls_config_load_file(error, "key", key_file,
92bb4cb1b0Sjsing 	    &keypair->key_mem, &keypair->key_len);
93bb4cb1b0Sjsing }
94bb4cb1b0Sjsing 
95bb4cb1b0Sjsing int
tls_keypair_set_key_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * key,size_t len)962974e8f1Sjsing tls_keypair_set_key_mem(struct tls_keypair *keypair, struct tls_error *error,
972974e8f1Sjsing     const uint8_t *key, size_t len)
98bb4cb1b0Sjsing {
99bb4cb1b0Sjsing 	tls_keypair_clear_key(keypair);
100bb4cb1b0Sjsing 	return tls_set_mem(&keypair->key_mem, &keypair->key_len, key, len);
101bb4cb1b0Sjsing }
102bb4cb1b0Sjsing 
103bb4cb1b0Sjsing int
tls_keypair_set_ocsp_staple_file(struct tls_keypair * keypair,struct tls_error * error,const char * ocsp_file)104bb4cb1b0Sjsing tls_keypair_set_ocsp_staple_file(struct tls_keypair *keypair,
105bb4cb1b0Sjsing     struct tls_error *error, const char *ocsp_file)
106bb4cb1b0Sjsing {
107bb4cb1b0Sjsing 	return tls_config_load_file(error, "ocsp", ocsp_file,
108bb4cb1b0Sjsing 	    &keypair->ocsp_staple, &keypair->ocsp_staple_len);
109bb4cb1b0Sjsing }
110bb4cb1b0Sjsing 
111bb4cb1b0Sjsing int
tls_keypair_set_ocsp_staple_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * staple,size_t len)112bb4cb1b0Sjsing tls_keypair_set_ocsp_staple_mem(struct tls_keypair *keypair,
1132974e8f1Sjsing     struct tls_error *error, const uint8_t *staple, size_t len)
114bb4cb1b0Sjsing {
115bb4cb1b0Sjsing 	return tls_set_mem(&keypair->ocsp_staple, &keypair->ocsp_staple_len,
116bb4cb1b0Sjsing 	    staple, len);
117bb4cb1b0Sjsing }
118bb4cb1b0Sjsing 
119bb4cb1b0Sjsing void
tls_keypair_free(struct tls_keypair * keypair)120bb4cb1b0Sjsing tls_keypair_free(struct tls_keypair *keypair)
121bb4cb1b0Sjsing {
122bb4cb1b0Sjsing 	if (keypair == NULL)
123bb4cb1b0Sjsing 		return;
124bb4cb1b0Sjsing 
125b3064b8aSjsing 	tls_keypair_clear_key(keypair);
126b3064b8aSjsing 
127b3064b8aSjsing 	free(keypair->cert_mem);
128b3064b8aSjsing 	free(keypair->ocsp_staple);
129b3064b8aSjsing 	free(keypair->pubkey_hash);
130bb4cb1b0Sjsing 
131bb4cb1b0Sjsing 	free(keypair);
132bb4cb1b0Sjsing }
133bb4cb1b0Sjsing 
134bb4cb1b0Sjsing int
tls_keypair_load_cert(struct tls_keypair * keypair,struct tls_error * error,X509 ** cert)135bb4cb1b0Sjsing tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
136bb4cb1b0Sjsing     X509 **cert)
137bb4cb1b0Sjsing {
138bb4cb1b0Sjsing 	char *errstr = "unknown";
139bb4cb1b0Sjsing 	BIO *cert_bio = NULL;
1400431a4acSinoguchi 	unsigned long ssl_err;
141bb4cb1b0Sjsing 	int rv = -1;
142bb4cb1b0Sjsing 
143bb4cb1b0Sjsing 	X509_free(*cert);
144bb4cb1b0Sjsing 	*cert = NULL;
145bb4cb1b0Sjsing 
146bb4cb1b0Sjsing 	if (keypair->cert_mem == NULL) {
147*7a756d37Sjoshua 		tls_error_set(error, TLS_ERROR_UNKNOWN,
148*7a756d37Sjoshua 		    "keypair has no certificate");
149bb4cb1b0Sjsing 		goto err;
150bb4cb1b0Sjsing 	}
151bb4cb1b0Sjsing 	if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem,
152bb4cb1b0Sjsing 	    keypair->cert_len)) == NULL) {
153*7a756d37Sjoshua 		tls_error_set(error, TLS_ERROR_UNKNOWN,
154*7a756d37Sjoshua 		    "failed to create certificate bio");
155bb4cb1b0Sjsing 		goto err;
156bb4cb1b0Sjsing 	}
157bb4cb1b0Sjsing 	if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb,
158bb4cb1b0Sjsing 	    NULL)) == NULL) {
159bb4cb1b0Sjsing 		if ((ssl_err = ERR_peek_error()) != 0)
160bb4cb1b0Sjsing 			errstr = ERR_error_string(ssl_err, NULL);
161*7a756d37Sjoshua 		tls_error_set(error, TLS_ERROR_UNKNOWN,
162*7a756d37Sjoshua 		    "failed to load certificate: %s", errstr);
163bb4cb1b0Sjsing 		goto err;
164bb4cb1b0Sjsing 	}
165bb4cb1b0Sjsing 
166bb4cb1b0Sjsing 	rv = 0;
167bb4cb1b0Sjsing 
168bb4cb1b0Sjsing  err:
169bb4cb1b0Sjsing 	BIO_free(cert_bio);
170bb4cb1b0Sjsing 
171bb4cb1b0Sjsing 	return (rv);
172bb4cb1b0Sjsing }
173