changeset 26370:5ca41ccc08ce

lib-dcrypt: Move shared secret derivation to dcrypt_openssl_echd_derive_secret Makes it possible to expose it on next commit.
author Aki Tuomi <aki.tuomi@open-xchange.com>
date Thu, 29 Aug 2019 16:43:45 +0300
parents c558e7a951e0
children 1d6ed0246396
files src/lib-dcrypt/dcrypt-openssl.c
diffstat 1 files changed, 54 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-dcrypt/dcrypt-openssl.c	Thu Aug 29 16:52:51 2019 +0300
+++ b/src/lib-dcrypt/dcrypt-openssl.c	Thu Aug 29 16:43:45 2019 +0300
@@ -721,10 +721,44 @@
 }
 
 static bool
+dcrypt_openssl_ecdh_derive_secret(struct dcrypt_private_key *priv_key,
+				  struct dcrypt_public_key *pub_key,
+				  buffer_t *shared_secret,
+				  const char **error_r)
+{
+	/* initialize */
+	EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(priv_key->key, NULL);
+	if (pctx == NULL ||
+	    EVP_PKEY_derive_init(pctx) != 1 ||
+	    EVP_PKEY_derive_set_peer(pctx, pub_key->key) != 1) {
+		EVP_PKEY_CTX_free(pctx);
+		return dcrypt_openssl_error(error_r);
+	}
+
+	/* derive */
+	size_t len;
+	if (EVP_PKEY_derive(pctx, NULL, &len) != 1) {
+		EVP_PKEY_CTX_free(pctx);
+		return dcrypt_openssl_error(error_r);
+	}
+	unsigned char buf[len];
+	if (EVP_PKEY_derive(pctx, buf, &len) != 1) {
+		EVP_PKEY_CTX_free(pctx);
+		return dcrypt_openssl_error(error_r);
+	}
+
+	EVP_PKEY_CTX_free(pctx);
+	buffer_append(shared_secret, buf, len);
+
+	return TRUE;
+}
+
+static bool
 dcrypt_openssl_ecdh_derive_secret_local(struct dcrypt_private_key *local_key,
 					buffer_t *R, buffer_t *S,
 					const char **error_r)
 {
+	bool ret;
 	i_assert(local_key != NULL && local_key->key != NULL);
 
 	EVP_PKEY *local = local_key->key;
@@ -769,36 +803,15 @@
 	}
 	EVP_PKEY_set1_EC_KEY(peer, ec_key);
 	EC_KEY_free(ec_key);
-	EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(local, NULL);
-
-	/* initialize derivation */
-	if (pctx == NULL ||
-	    EVP_PKEY_derive_init(pctx) != 1 ||
-	    EVP_PKEY_derive_set_peer(pctx, peer) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		EVP_PKEY_free(peer);
-		return dcrypt_openssl_error(error_r);
-	}
-
-	/* have to do it twice to get the data length */
-	size_t len;
-	if (EVP_PKEY_derive(pctx, NULL, &len) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		EVP_PKEY_free(peer);
-		return dcrypt_openssl_error(error_r);
-	}
-
-	unsigned char buf[len];
-	memset(buf,0,len);
-	if (EVP_PKEY_derive(pctx, buf, &len) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		EVP_PKEY_free(peer);
-		return dcrypt_openssl_error(error_r);
-	}
-	EVP_PKEY_CTX_free(pctx);
-	buffer_append(S, buf, len);
+
+	struct dcrypt_public_key pub_key;
+	i_zero(&pub_key);
+	pub_key.key = peer;
+
+	ret = dcrypt_openssl_ecdh_derive_secret(local_key, &pub_key, S, error_r);
+
 	EVP_PKEY_free(peer);
-	return TRUE;
+	return ret;
 }
 
 static bool
@@ -807,6 +820,7 @@
 				       const char **error_r)
 {
 	i_assert(peer_key != NULL && peer_key->key != NULL);
+	bool ret;
 
 	/* ensure peer_key is EC key */
 	EVP_PKEY *local = NULL;
@@ -823,36 +837,22 @@
 	if (!dcrypt_openssl_generate_ec_key(nid, &local, error_r))
 		return FALSE;
 
-	/* initialize */
-	EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(local, NULL);
-	if (pctx == NULL ||
-	    EVP_PKEY_derive_init(pctx) != 1 ||
-	    EVP_PKEY_derive_set_peer(pctx, peer) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		return dcrypt_openssl_error(error_r);
+	struct dcrypt_private_key priv_key;
+	i_zero(&priv_key);
+	priv_key.key = local;
+
+	if (!(ret = dcrypt_openssl_ecdh_derive_secret(&priv_key, peer_key, S,
+						 error_r))) {
+		EVP_PKEY_free(local);
+		return FALSE;
 	}
 
-	/* derive */
-	size_t len;
-	if (EVP_PKEY_derive(pctx, NULL, &len) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		return dcrypt_openssl_error(error_r);
-	}
-	unsigned char buf[len];
-	if (EVP_PKEY_derive(pctx, buf, &len) != 1) {
-		EVP_PKEY_CTX_free(pctx);
-		return dcrypt_openssl_error(error_r);
-	}
-
-	EVP_PKEY_CTX_free(pctx);
-	buffer_append(S, buf, len);
-
 	/* get ephemeral key (=R) */
 	BN_CTX *bn_ctx = BN_CTX_new();
 	const EC_POINT *pub = EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(local));
 	const EC_GROUP *grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(local));
-	len = EC_POINT_point2oct(grp, pub, POINT_CONVERSION_COMPRESSED,
-				 NULL, 0, bn_ctx);
+	size_t len = EC_POINT_point2oct(grp, pub, POINT_CONVERSION_COMPRESSED,
+					NULL, 0, bn_ctx);
 	unsigned char R_buf[len];
 	EC_POINT_point2oct(grp, pub, POINT_CONVERSION_COMPRESSED,
 			   R_buf, len, bn_ctx);
@@ -860,7 +860,7 @@
 	buffer_append(R, R_buf, len);
 	EVP_PKEY_free(local);
 
-	return TRUE;
+	return ret;
 }
 
 static bool