tpm2-tools/0016-openssl-Convert-deprecated-ECDH_compute_key-to-EVP_P.patch
Štěpán Horáček d8b5733ac7 tpm2-tools: Fix segfault and add support for OpenSSL 3
The segfault was caused by calling tpm2 command on ppc64le without any
additional arguments.

Resolves: rhbz#1989617

Signed-off-by: Štěpán Horáček <shoracek@redhat.com>
2021-10-05 12:20:18 +02:00

287 lines
7.8 KiB
Diff

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