1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: tls_keypair.c,v 1.8 2021/01/05 17:37:12 jsing Exp $ */
272c33676SMaxim Ag /*
372c33676SMaxim Ag * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
472c33676SMaxim Ag *
572c33676SMaxim Ag * Permission to use, copy, modify, and distribute this software for any
672c33676SMaxim Ag * purpose with or without fee is hereby granted, provided that the above
772c33676SMaxim Ag * copyright notice and this permission notice appear in all copies.
872c33676SMaxim Ag *
972c33676SMaxim Ag * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1072c33676SMaxim Ag * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1172c33676SMaxim Ag * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1272c33676SMaxim Ag * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1372c33676SMaxim Ag * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1472c33676SMaxim Ag * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1572c33676SMaxim Ag * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1672c33676SMaxim Ag */
1772c33676SMaxim Ag
1872c33676SMaxim Ag #include <openssl/bio.h>
1972c33676SMaxim Ag #include <openssl/err.h>
2072c33676SMaxim Ag #include <openssl/pem.h>
2172c33676SMaxim Ag
2272c33676SMaxim Ag #include <tls.h>
2372c33676SMaxim Ag
2472c33676SMaxim Ag #include "tls_internal.h"
2572c33676SMaxim Ag
2672c33676SMaxim Ag struct tls_keypair *
tls_keypair_new(void)2772c33676SMaxim Ag tls_keypair_new(void)
2872c33676SMaxim Ag {
2972c33676SMaxim Ag return calloc(1, sizeof(struct tls_keypair));
3072c33676SMaxim Ag }
3172c33676SMaxim Ag
3272c33676SMaxim Ag static int
tls_keypair_pubkey_hash(struct tls_keypair * keypair,struct tls_error * error)3372c33676SMaxim Ag tls_keypair_pubkey_hash(struct tls_keypair *keypair, struct tls_error *error)
3472c33676SMaxim Ag {
3572c33676SMaxim Ag X509 *cert = NULL;
3672c33676SMaxim Ag int rv = -1;
3772c33676SMaxim Ag
3872c33676SMaxim Ag free(keypair->pubkey_hash);
3972c33676SMaxim Ag keypair->pubkey_hash = NULL;
4072c33676SMaxim Ag
4172c33676SMaxim Ag if (keypair->cert_mem == NULL) {
4272c33676SMaxim Ag rv = 0;
4372c33676SMaxim Ag goto done;
4472c33676SMaxim Ag }
4572c33676SMaxim Ag
4672c33676SMaxim Ag if (tls_keypair_load_cert(keypair, error, &cert) == -1)
4772c33676SMaxim Ag goto err;
4872c33676SMaxim Ag if (tls_cert_pubkey_hash(cert, &keypair->pubkey_hash) == -1)
4972c33676SMaxim Ag goto err;
5072c33676SMaxim Ag
5172c33676SMaxim Ag rv = 0;
5272c33676SMaxim Ag
5372c33676SMaxim Ag err:
5472c33676SMaxim Ag X509_free(cert);
5572c33676SMaxim Ag done:
5672c33676SMaxim Ag return (rv);
5772c33676SMaxim Ag }
5872c33676SMaxim Ag
5972c33676SMaxim Ag void
tls_keypair_clear_key(struct tls_keypair * keypair)6072c33676SMaxim Ag tls_keypair_clear_key(struct tls_keypair *keypair)
6172c33676SMaxim Ag {
6272c33676SMaxim Ag freezero(keypair->key_mem, keypair->key_len);
6372c33676SMaxim Ag keypair->key_mem = NULL;
6472c33676SMaxim Ag keypair->key_len = 0;
6572c33676SMaxim Ag }
6672c33676SMaxim Ag
6772c33676SMaxim Ag int
tls_keypair_set_cert_file(struct tls_keypair * keypair,struct tls_error * error,const char * cert_file)6872c33676SMaxim Ag tls_keypair_set_cert_file(struct tls_keypair *keypair, struct tls_error *error,
6972c33676SMaxim Ag const char *cert_file)
7072c33676SMaxim Ag {
7172c33676SMaxim Ag if (tls_config_load_file(error, "certificate", cert_file,
7272c33676SMaxim Ag &keypair->cert_mem, &keypair->cert_len) == -1)
7372c33676SMaxim Ag return -1;
7472c33676SMaxim Ag return tls_keypair_pubkey_hash(keypair, error);
7572c33676SMaxim Ag }
7672c33676SMaxim Ag
7772c33676SMaxim Ag int
tls_keypair_set_cert_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * cert,size_t len)7872c33676SMaxim Ag tls_keypair_set_cert_mem(struct tls_keypair *keypair, struct tls_error *error,
7972c33676SMaxim Ag const uint8_t *cert, size_t len)
8072c33676SMaxim Ag {
8172c33676SMaxim Ag if (tls_set_mem(&keypair->cert_mem, &keypair->cert_len, cert, len) == -1)
8272c33676SMaxim Ag return -1;
8372c33676SMaxim Ag return tls_keypair_pubkey_hash(keypair, error);
8472c33676SMaxim Ag }
8572c33676SMaxim Ag
8672c33676SMaxim Ag int
tls_keypair_set_key_file(struct tls_keypair * keypair,struct tls_error * error,const char * key_file)8772c33676SMaxim Ag tls_keypair_set_key_file(struct tls_keypair *keypair, struct tls_error *error,
8872c33676SMaxim Ag const char *key_file)
8972c33676SMaxim Ag {
9072c33676SMaxim Ag tls_keypair_clear_key(keypair);
9172c33676SMaxim Ag return tls_config_load_file(error, "key", key_file,
9272c33676SMaxim Ag &keypair->key_mem, &keypair->key_len);
9372c33676SMaxim Ag }
9472c33676SMaxim Ag
9572c33676SMaxim Ag int
tls_keypair_set_key_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * key,size_t len)9672c33676SMaxim Ag tls_keypair_set_key_mem(struct tls_keypair *keypair, struct tls_error *error,
9772c33676SMaxim Ag const uint8_t *key, size_t len)
9872c33676SMaxim Ag {
9972c33676SMaxim Ag tls_keypair_clear_key(keypair);
10072c33676SMaxim Ag return tls_set_mem(&keypair->key_mem, &keypair->key_len, key, len);
10172c33676SMaxim Ag }
10272c33676SMaxim Ag
10372c33676SMaxim Ag int
tls_keypair_set_ocsp_staple_file(struct tls_keypair * keypair,struct tls_error * error,const char * ocsp_file)10472c33676SMaxim Ag tls_keypair_set_ocsp_staple_file(struct tls_keypair *keypair,
10572c33676SMaxim Ag struct tls_error *error, const char *ocsp_file)
10672c33676SMaxim Ag {
10772c33676SMaxim Ag return tls_config_load_file(error, "ocsp", ocsp_file,
10872c33676SMaxim Ag &keypair->ocsp_staple, &keypair->ocsp_staple_len);
10972c33676SMaxim Ag }
11072c33676SMaxim Ag
11172c33676SMaxim Ag int
tls_keypair_set_ocsp_staple_mem(struct tls_keypair * keypair,struct tls_error * error,const uint8_t * staple,size_t len)11272c33676SMaxim Ag tls_keypair_set_ocsp_staple_mem(struct tls_keypair *keypair,
11372c33676SMaxim Ag struct tls_error *error, const uint8_t *staple, size_t len)
11472c33676SMaxim Ag {
11572c33676SMaxim Ag return tls_set_mem(&keypair->ocsp_staple, &keypair->ocsp_staple_len,
11672c33676SMaxim Ag staple, len);
11772c33676SMaxim Ag }
11872c33676SMaxim Ag
11972c33676SMaxim Ag void
tls_keypair_free(struct tls_keypair * keypair)12072c33676SMaxim Ag tls_keypair_free(struct tls_keypair *keypair)
12172c33676SMaxim Ag {
12272c33676SMaxim Ag if (keypair == NULL)
12372c33676SMaxim Ag return;
12472c33676SMaxim Ag
12572c33676SMaxim Ag tls_keypair_clear_key(keypair);
12672c33676SMaxim Ag
12772c33676SMaxim Ag free(keypair->cert_mem);
12872c33676SMaxim Ag free(keypair->ocsp_staple);
12972c33676SMaxim Ag free(keypair->pubkey_hash);
13072c33676SMaxim Ag
13172c33676SMaxim Ag free(keypair);
13272c33676SMaxim Ag }
13372c33676SMaxim Ag
13472c33676SMaxim Ag int
tls_keypair_load_cert(struct tls_keypair * keypair,struct tls_error * error,X509 ** cert)13572c33676SMaxim Ag tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
13672c33676SMaxim Ag X509 **cert)
13772c33676SMaxim Ag {
13872c33676SMaxim Ag char *errstr = "unknown";
13972c33676SMaxim Ag BIO *cert_bio = NULL;
140*de0e0e4dSAntonio Huete Jimenez unsigned long ssl_err;
14172c33676SMaxim Ag int rv = -1;
14272c33676SMaxim Ag
14372c33676SMaxim Ag X509_free(*cert);
14472c33676SMaxim Ag *cert = NULL;
14572c33676SMaxim Ag
14672c33676SMaxim Ag if (keypair->cert_mem == NULL) {
14772c33676SMaxim Ag tls_error_set(error, "keypair has no certificate");
14872c33676SMaxim Ag goto err;
14972c33676SMaxim Ag }
15072c33676SMaxim Ag if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem,
15172c33676SMaxim Ag keypair->cert_len)) == NULL) {
15272c33676SMaxim Ag tls_error_set(error, "failed to create certificate bio");
15372c33676SMaxim Ag goto err;
15472c33676SMaxim Ag }
15572c33676SMaxim Ag if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb,
15672c33676SMaxim Ag NULL)) == NULL) {
15772c33676SMaxim Ag if ((ssl_err = ERR_peek_error()) != 0)
15872c33676SMaxim Ag errstr = ERR_error_string(ssl_err, NULL);
15972c33676SMaxim Ag tls_error_set(error, "failed to load certificate: %s", errstr);
16072c33676SMaxim Ag goto err;
16172c33676SMaxim Ag }
16272c33676SMaxim Ag
16372c33676SMaxim Ag rv = 0;
16472c33676SMaxim Ag
16572c33676SMaxim Ag err:
16672c33676SMaxim Ag BIO_free(cert_bio);
16772c33676SMaxim Ag
16872c33676SMaxim Ag return (rv);
16972c33676SMaxim Ag }
170