summary refs log tree commit diff
path: root/tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'tls.c')
-rw-r--r--tls.c139
1 files changed, 108 insertions, 31 deletions
diff --git a/tls.c b/tls.c
index 26adb2b..91f20cf 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>
  *
@@ -387,12 +387,113 @@ use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len)
 	return (ret);
 }
 
+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 &&
@@ -412,38 +513,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;
 	}
@@ -458,9 +536,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