Blame SOURCES/0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch

05e1a9
From 0caac28c1fa2d62dbf7c5a6c65346f6d3399d22c Mon Sep 17 00:00:00 2001
05e1a9
From: Petr Gotthard <petr.gotthard@centrum.cz>
05e1a9
Date: Sun, 15 Aug 2021 16:26:06 +0200
05e1a9
Subject: [PATCH 15/17] openssl: Convert deprecated ECDH_compute_key to
05e1a9
 EVP_PKEY_derive
05e1a9
05e1a9
The EC_KEY functions are replaced by corresponding EVP_PKEY functions.
05e1a9
The tpm2_get_EC_public_key function is replaced by convert_pubkey_ECC
05e1a9
from lib/tpm2_convert.c.
05e1a9
05e1a9
Signed-off-by: Petr Gotthard <petr.gotthard@centrum.cz>
05e1a9
---
05e1a9
 lib/tpm2_kdfe.c | 186 +++++++++++++++++++++++-------------------------
05e1a9
 1 file changed, 89 insertions(+), 97 deletions(-)
05e1a9
05e1a9
diff --git a/lib/tpm2_kdfe.c b/lib/tpm2_kdfe.c
05e1a9
index 84718b9f..91027e32 100644
05e1a9
--- a/lib/tpm2_kdfe.c
05e1a9
+++ b/lib/tpm2_kdfe.c
05e1a9
@@ -5,12 +5,16 @@
05e1a9
 #include <string.h>
05e1a9
 
05e1a9
 #include <openssl/bn.h>
05e1a9
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
05e1a9
 #include <openssl/ecdh.h>
05e1a9
-
05e1a9
+#else
05e1a9
+#include <openssl/core_names.h>
05e1a9
+#endif
05e1a9
 #include <tss2/tss2_tpm2_types.h>
05e1a9
 #include <tss2/tss2_mu.h>
05e1a9
 
05e1a9
 #include "log.h"
05e1a9
+#include "tpm2_convert.h"
05e1a9
 #include "tpm2_openssl.h"
05e1a9
 #include "tpm2_alg_util.h"
05e1a9
 #include "tpm2_util.h"
05e1a9
@@ -65,72 +69,18 @@ TSS2_RC tpm2_kdfe(
05e1a9
     return rval;
05e1a9
 }
05e1a9
 
05e1a9
-static EC_POINT * tpm2_get_EC_public_key(TPM2B_PUBLIC *public) {
05e1a9
-    EC_POINT *q = NULL;
05e1a9
-    BIGNUM *bn_qx, *bn_qy;
05e1a9
-    EC_KEY *key;
05e1a9
-    const EC_GROUP *group;
05e1a9
-    bool rval;
05e1a9
-    TPMS_ECC_PARMS *tpm_ecc   = &public->publicArea.parameters.eccDetail;
05e1a9
-    TPMS_ECC_POINT *tpm_point = &public->publicArea.unique.ecc;
05e1a9
-
05e1a9
-    int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID);
05e1a9
-    if (nid < 0) {
05e1a9
-        return NULL;
05e1a9
-    }
05e1a9
-
05e1a9
-    key = EC_KEY_new_by_curve_name(nid);
05e1a9
-    if (!key) {
05e1a9
-        LOG_ERR("Failed to create EC key from nid");
05e1a9
-        return NULL;
05e1a9
-    }
05e1a9
-
05e1a9
-    bn_qx = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL);
05e1a9
-    bn_qy = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL);
05e1a9
-    if ((bn_qx == NULL) || (bn_qy == NULL)) {
05e1a9
-        LOG_ERR("Could not convert EC public key to BN");
05e1a9
-        goto out;
05e1a9
-    }
05e1a9
-    group = EC_KEY_get0_group(key);
05e1a9
-    if (!group) {
05e1a9
-        LOG_ERR("EC key missing group");
05e1a9
-        goto out;
05e1a9
-    }
05e1a9
-    q = EC_POINT_new(group);
05e1a9
-    if (q == NULL) {
05e1a9
-        LOG_ERR("Could not allocate EC_POINT");
05e1a9
-        goto out;
05e1a9
-    }
05e1a9
-
05e1a9
-    rval = EC_POINT_set_affine_coordinates_tss(group, q, bn_qx, bn_qy, NULL);
05e1a9
-    if (rval == false) {
05e1a9
-        LOG_ERR("Could not set affine_coordinates");
05e1a9
-        EC_POINT_free(q);
05e1a9
-        q = NULL;
05e1a9
-    }
05e1a9
-
05e1a9
-out:
05e1a9
-    if (bn_qx) {
05e1a9
-        BN_free(bn_qx);
05e1a9
-    }
05e1a9
-    if (bn_qy) {
05e1a9
-        BN_free(bn_qy);
05e1a9
-    }
05e1a9
-    if (key) {
05e1a9
-        EC_KEY_free(key);
05e1a9
-    }
05e1a9
-
05e1a9
-    return q;
05e1a9
-}
05e1a9
-
05e1a9
-
05e1a9
-static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) {
05e1a9
-    BIGNUM *x = BN_new();
05e1a9
-    BIGNUM *y = BN_new();
05e1a9
-    const EC_POINT *pubkey = EC_KEY_get0_public_key(key);
05e1a9
+static bool get_public_key_from_ec_key(EVP_PKEY *pkey, TPMS_ECC_POINT *point) {
05e1a9
+    BIGNUM *x = NULL;
05e1a9
+    BIGNUM *y = NULL;
05e1a9
     unsigned int nbx, nby;
05e1a9
     bool result = false;
05e1a9
 
05e1a9
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
05e1a9
+    EC_KEY *key = EVP_PKEY_get0_EC_KEY(pkey);
05e1a9
+    const EC_POINT *pubkey = EC_KEY_get0_public_key(key);
05e1a9
+
05e1a9
+    x = BN_new();
05e1a9
+    y = BN_new();
05e1a9
     if ((x == NULL) || (y == NULL) || (pubkey == NULL)) {
05e1a9
         LOG_ERR("Failed to allocate memory to store EC public key.");
05e1a9
         goto out;
05e1a9
@@ -138,6 +88,18 @@ static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) {
05e1a9
 
05e1a9
     EC_POINT_get_affine_coordinates_tss(EC_KEY_get0_group(key),
05e1a9
             pubkey, x, y, NULL);
05e1a9
+#else
05e1a9
+    int rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x);
05e1a9
+    if (!rc) {
05e1a9
+        LOG_ERR("Failed to get EC public key X.");
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
+    rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y);
05e1a9
+    if (!rc) {
05e1a9
+        LOG_ERR("Failed to get EC public key Y.");
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
+#endif
05e1a9
     nbx = BN_num_bytes(x);
05e1a9
     nby = BN_num_bytes(y);
05e1a9
     if ((nbx > sizeof(point->x.buffer))||
05e1a9
@@ -153,29 +115,41 @@ static bool get_public_key_from_ec_key(EC_KEY *key, TPMS_ECC_POINT *point) {
05e1a9
     result = true;
05e1a9
 
05e1a9
 out:
05e1a9
-    if (x) {
05e1a9
-        BN_free(x);
05e1a9
-    }
05e1a9
-    if (y) {
05e1a9
-        BN_free(y);
05e1a9
-    }
05e1a9
+    BN_free(x);
05e1a9
+    BN_free(y);
05e1a9
     return result;
05e1a9
 }
05e1a9
 
05e1a9
 
05e1a9
-static int get_ECDH_shared_secret(EC_KEY *key,
05e1a9
-        const EC_POINT *p_pub, TPM2B_ECC_PARAMETER *secret) {
05e1a9
+static int get_ECDH_shared_secret(EVP_PKEY *pkey,
05e1a9
+        EVP_PKEY *p_pub, TPM2B_ECC_PARAMETER *secret) {
05e1a9
 
05e1a9
-    int shared_secret_length;
05e1a9
+    EVP_PKEY_CTX *ctx;
05e1a9
+    int result = -1;
05e1a9
 
05e1a9
-    shared_secret_length = EC_GROUP_get_degree(EC_KEY_get0_group(key));
05e1a9
-    shared_secret_length = (shared_secret_length + 7) / 8;
05e1a9
-    if ((size_t) shared_secret_length > sizeof(secret->buffer)) {
05e1a9
+    ctx = EVP_PKEY_CTX_new(pkey, NULL);
05e1a9
+    if (!ctx)
05e1a9
         return -1;
05e1a9
-    }
05e1a9
-    secret->size = ECDH_compute_key(secret->buffer,
05e1a9
-            shared_secret_length, p_pub, key, NULL);
05e1a9
-    return secret->size;
05e1a9
+
05e1a9
+    int rc = EVP_PKEY_derive_init(ctx);
05e1a9
+    if (rc <= 0)
05e1a9
+        goto out;
05e1a9
+
05e1a9
+    rc = EVP_PKEY_derive_set_peer(ctx, p_pub);
05e1a9
+    if (rc <= 0)
05e1a9
+        goto out;
05e1a9
+
05e1a9
+    size_t shared_secret_length = sizeof(secret->buffer);
05e1a9
+    rc = EVP_PKEY_derive(ctx, secret->buffer, &shared_secret_length);
05e1a9
+    if (rc <= 0)
05e1a9
+        goto out;
05e1a9
+
05e1a9
+    secret->size = shared_secret_length;
05e1a9
+    result = secret->size;
05e1a9
+
05e1a9
+out:
05e1a9
+    EVP_PKEY_CTX_free(ctx);
05e1a9
+    return result;
05e1a9
 }
05e1a9
 
05e1a9
 
05e1a9
@@ -190,25 +164,42 @@ bool ecdh_derive_seed_and_encrypted_seed(
05e1a9
     TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg;
05e1a9
     UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_name_alg);
05e1a9
     bool result = false;
05e1a9
-    EC_KEY *key = NULL;
05e1a9
-    EC_POINT *qsv = NULL;
05e1a9
+    EVP_PKEY_CTX *ctx;
05e1a9
+    EVP_PKEY *pkey = NULL;
05e1a9
+    EVP_PKEY *qsv = NULL;
05e1a9
     TPMS_ECC_POINT qeu;
05e1a9
     bool qeu_is_valid;
05e1a9
     TPM2B_ECC_PARAMETER ecc_secret;
05e1a9
 
05e1a9
     // generate an ephemeral key
05e1a9
     int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID);
05e1a9
-    if (nid >= 0) {
05e1a9
-        key = EC_KEY_new_by_curve_name(nid);
05e1a9
-    }
05e1a9
-    if (key == NULL) {
05e1a9
-        LOG_ERR("Failed to create EC key from curveID");
05e1a9
+
05e1a9
+    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
05e1a9
+    if (!ctx) {
05e1a9
+        LOG_ERR("Failed to create key creation context");
05e1a9
         return false;
05e1a9
     }
05e1a9
-    EC_KEY_generate_key(key);
05e1a9
+
05e1a9
+    int rc = EVP_PKEY_keygen_init(ctx);
05e1a9
+    if (rc <= 0) {
05e1a9
+        LOG_ERR("Failed to initialize key creation");
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
+
05e1a9
+    rc = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
05e1a9
+    if (rc <= 0) {
05e1a9
+        LOG_ERR("Failed to set EC curve NID %i", nid);
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
+
05e1a9
+    rc = EVP_PKEY_keygen(ctx, &pkey);
05e1a9
+    if (rc <= 0) {
05e1a9
+        LOG_ERR("Failed to generate the ephemeral EC key");
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
 
05e1a9
     // get public key for the ephemeral key
05e1a9
-    qeu_is_valid = get_public_key_from_ec_key(key, &qeu);
05e1a9
+    qeu_is_valid = get_public_key_from_ec_key(pkey, &qeu);
05e1a9
     if (qeu_is_valid == false) {
05e1a9
         LOG_ERR("Could not get the ECC public key");
05e1a9
         goto out;
05e1a9
@@ -226,13 +217,17 @@ bool ecdh_derive_seed_and_encrypted_seed(
05e1a9
     out_sym_seed->size = offset;
05e1a9
 
05e1a9
     /* get parents public key */
05e1a9
-    qsv = tpm2_get_EC_public_key(parent_pub);
05e1a9
+    qsv = convert_pubkey_ECC(&parent_pub->publicArea);
05e1a9
     if (qsv == NULL) {
05e1a9
         LOG_ERR("Could not get parent's public key");
05e1a9
         goto out;
05e1a9
     }
05e1a9
 
05e1a9
-    get_ECDH_shared_secret(key, qsv, &ecc_secret);
05e1a9
+    rc = get_ECDH_shared_secret(pkey, qsv, &ecc_secret);
05e1a9
+    if (rc <= 0) {
05e1a9
+        LOG_ERR("Could not derive shared secret");
05e1a9
+        goto out;
05e1a9
+    }
05e1a9
 
05e1a9
     /* derive seed using KDFe */
05e1a9
     TPM2B_ECC_PARAMETER *party_u_info = &qeu.x;
05e1a9
@@ -244,11 +239,8 @@ bool ecdh_derive_seed_and_encrypted_seed(
05e1a9
     result = true;
05e1a9
 
05e1a9
 out:
05e1a9
-    if (qsv) {
05e1a9
-        EC_POINT_free(qsv);
05e1a9
-    }
05e1a9
-    if (key) {
05e1a9
-        EC_KEY_free(key);
05e1a9
-    }
05e1a9
+    EVP_PKEY_free(qsv);
05e1a9
+    EVP_PKEY_free(pkey);
05e1a9
+    EVP_PKEY_CTX_free(ctx);
05e1a9
     return result;
05e1a9
 }
05e1a9
-- 
05e1a9
2.31.1
05e1a9