diff options
Diffstat (limited to '')
-rw-r--r-- | tls.c | 139 |
1 files changed, 108 insertions, 31 deletions
diff --git a/tls.c b/tls.c index 3d6723b..262ec3d 100644 --- a/tls.c +++ b/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.85 2020/05/24 15:12:54 jsing Exp $ */ +/* $OpenBSD: tls.c,v 1.89 2021/02/01 15:35:41 tb Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -326,12 +326,113 @@ tls_cert_pubkey_hash(X509 *cert, char **hash) return (rv); } +static int +tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pkey) +{ + BIO *bio = NULL; + X509 *x509 = NULL; + char *mem; + size_t len; + int ret = -1; + + *pkey = NULL; + + if (ctx->config->use_fake_private_key) { + mem = keypair->cert_mem; + len = keypair->cert_len; + } else { + mem = keypair->key_mem; + len = keypair->key_len; + } + + if (mem == NULL) + return (0); + + if (len > INT_MAX) { + tls_set_errorx(ctx, ctx->config->use_fake_private_key ? + "cert too long" : "key too long"); + goto err; + } + + if ((bio = BIO_new_mem_buf(mem, len)) == NULL) { + tls_set_errorx(ctx, "failed to create buffer"); + goto err; + } + + if (ctx->config->use_fake_private_key) { + if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to read X509 certificate"); + goto err; + } + if ((*pkey = X509_get_pubkey(x509)) == NULL) { + tls_set_errorx(ctx, "failed to retrieve pubkey"); + goto err; + } + } else { + if ((*pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to read private key"); + goto err; + } + } + + ret = 0; + err: + BIO_free(bio); + X509_free(x509); + return (ret); +} + +static int +tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey) +{ + RSA *rsa = NULL; + EC_KEY *eckey = NULL; + int ret = -1; + + /* Only install the pubkey hash if fake private keys are used. */ + if (!ctx->config->skip_private_key_check) + return (0); + + if (keypair->pubkey_hash == NULL) { + tls_set_errorx(ctx, "public key hash not set"); + goto err; + } + + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_RSA: + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL || + RSA_set_ex_data(rsa, 0, keypair->pubkey_hash) == 0) { + tls_set_errorx(ctx, "RSA key setup failure"); + goto err; + } + break; + case EVP_PKEY_EC: + if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL || + ECDSA_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) { + tls_set_errorx(ctx, "EC key setup failure"); + goto err; + } + break; + default: + tls_set_errorx(ctx, "incorrect key type"); + goto err; + } + + ret = 0; + + err: + RSA_free(rsa); + EC_KEY_free(eckey); + return (ret); +} + int tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, struct tls_keypair *keypair, int required) { EVP_PKEY *pkey = NULL; - BIO *bio = NULL; if (!required && keypair->cert_mem == NULL && @@ -351,38 +452,15 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, } } - if (keypair->key_mem != NULL) { - if (keypair->key_len > INT_MAX) { - tls_set_errorx(ctx, "key too long"); - goto err; - } - - if ((bio = BIO_new_mem_buf(keypair->key_mem, - keypair->key_len)) == NULL) { - tls_set_errorx(ctx, "failed to create buffer"); - goto err; - } - if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, - NULL)) == NULL) { - tls_set_errorx(ctx, "failed to read private key"); + if (tls_keypair_to_pkey(ctx, keypair, &pkey) == -1) + goto err; + if (pkey != NULL) { + if (tls_keypair_setup_pkey(ctx, keypair, pkey) == -1) goto err; - } - - if (keypair->pubkey_hash != NULL) { - RSA *rsa; - /* XXX only RSA for now for relayd privsep */ - if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { - RSA_set_ex_data(rsa, 0, keypair->pubkey_hash); - RSA_free(rsa); - } - } - if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) { tls_set_errorx(ctx, "failed to load private key"); goto err; } - BIO_free(bio); - bio = NULL; EVP_PKEY_free(pkey); pkey = NULL; } @@ -397,9 +475,8 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, err: EVP_PKEY_free(pkey); - BIO_free(bio); - return (1); + return (-1); } int |