241 lines
7.6 KiB
Diff
241 lines
7.6 KiB
Diff
From 317c1ea1d9893d6f4f837196648c53b7f7dd762f Mon Sep 17 00:00:00 2001
|
|
From: Petr Gotthard <petr.gotthard@centrum.cz>
|
|
Date: Sun, 15 Aug 2021 17:22:44 +0200
|
|
Subject: [PATCH 16/17] openssl: Reimplement RSA OAEP encryption using EVP
|
|
functions
|
|
|
|
The RSA_padding_add_PKCS1_OAEP_mgf1 is deprecated and the entire
|
|
semi-custom implementation of OAEP is unnecessary.
|
|
The Part 1, B.10.3 talks about a standard OAEP with a given label,
|
|
which can be easily implemented using the standard EVP functions.
|
|
Also, the public key retrieval can be replaced by invocation of
|
|
convert_pubkey_RSA from lib/tpm2_convert.c
|
|
|
|
Signed-off-by: Petr Gotthard <petr.gotthard@centrum.cz>
|
|
---
|
|
lib/tpm2_identity_util.c | 162 +++++++++++----------------------------
|
|
1 file changed, 43 insertions(+), 119 deletions(-)
|
|
|
|
diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c
|
|
index ba0c0e1c..b04a56d6 100644
|
|
--- a/lib/tpm2_identity_util.c
|
|
+++ b/lib/tpm2_identity_util.c
|
|
@@ -10,6 +10,7 @@
|
|
|
|
#include "log.h"
|
|
#include "tpm2_alg_util.h"
|
|
+#include "tpm2_convert.h"
|
|
#include "tpm2_identity_util.h"
|
|
#include "tpm2_kdfa.h"
|
|
#include "tpm2_kdfe.h"
|
|
@@ -17,73 +18,6 @@
|
|
|
|
// Identity-related functionality that the TPM normally does, but using OpenSSL
|
|
|
|
-#if defined(LIBRESSL_VERSION_NUMBER)
|
|
-static int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
|
- const unsigned char *from, int flen, const unsigned char *param, int plen,
|
|
- const EVP_MD *md, const EVP_MD *mgf1md) {
|
|
-
|
|
- int ret = 0;
|
|
- int i, emlen = tlen - 1;
|
|
- unsigned char *db, *seed;
|
|
- unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
|
|
- int mdlen;
|
|
-
|
|
- if (md == NULL)
|
|
- md = EVP_sha1();
|
|
- if (mgf1md == NULL)
|
|
- mgf1md = md;
|
|
-
|
|
- mdlen = EVP_MD_size(md);
|
|
-
|
|
- if (flen > emlen - 2 * mdlen - 1) {
|
|
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
|
|
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (emlen < 2 * mdlen + 1) {
|
|
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
|
|
- RSA_R_KEY_SIZE_TOO_SMALL);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- to[0] = 0;
|
|
- seed = to + 1;
|
|
- db = to + mdlen + 1;
|
|
-
|
|
- if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
|
|
- return 0;
|
|
- memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
|
|
- db[emlen - flen - mdlen - 1] = 0x01;
|
|
- memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
|
|
- if (RAND_bytes(seed, mdlen) <= 0)
|
|
- return 0;
|
|
-
|
|
- dbmask = OPENSSL_malloc(emlen - mdlen);
|
|
- if (dbmask == NULL) {
|
|
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
|
|
- goto err;
|
|
- for (i = 0; i < emlen - mdlen; i++)
|
|
- db[i] ^= dbmask[i];
|
|
-
|
|
- if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
|
|
- goto err;
|
|
- for (i = 0; i < mdlen; i++)
|
|
- seed[i] ^= seedmask[i];
|
|
-
|
|
- ret = 1;
|
|
-
|
|
-err:
|
|
- OPENSSL_free(dbmask);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-#endif
|
|
-
|
|
static TPM2_KEY_BITS get_pub_asym_key_bits(TPM2B_PUBLIC *public) {
|
|
|
|
TPMU_PUBLIC_PARMS *p = &public->publicArea.parameters;
|
|
@@ -102,19 +36,13 @@ static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed,
|
|
TPM2B_PUBLIC *parent_pub, unsigned char *label, int label_len,
|
|
TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) {
|
|
bool rval = false;
|
|
- RSA *rsa = NULL;
|
|
-
|
|
- // Public modulus (RSA-only!)
|
|
- TPMI_RSA_KEY_BITS mod_size_bits =
|
|
- parent_pub->publicArea.parameters.rsaDetail.keyBits;
|
|
- UINT16 mod_size = mod_size_bits / 8;
|
|
- TPM2B *pub_key_val = (TPM2B *) &parent_pub->publicArea.unique.rsa;
|
|
- unsigned char *pub_modulus = malloc(mod_size);
|
|
- if (pub_modulus == NULL) {
|
|
- LOG_ERR("Failed to allocate memory to store public key's modulus.");
|
|
+ EVP_PKEY_CTX *ctx = NULL;
|
|
+
|
|
+ EVP_PKEY *pkey = convert_pubkey_RSA(&parent_pub->publicArea);
|
|
+ if (pkey == NULL) {
|
|
+ LOG_ERR("Failed to retrieve public key");
|
|
return false;
|
|
}
|
|
- memcpy(pub_modulus, pub_key_val->buffer, mod_size);
|
|
|
|
TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg;
|
|
|
|
@@ -122,70 +50,66 @@ static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed,
|
|
* RSA Secret Sharing uses a randomly generated seed (Part 1, B.10.3).
|
|
*/
|
|
protection_seed->size = tpm2_alg_util_get_hash_size(parent_name_alg);
|
|
- int return_code = RAND_bytes(protection_seed->buffer, protection_seed->size);
|
|
- if (return_code != 1) {
|
|
+ int rc = RAND_bytes(protection_seed->buffer, protection_seed->size);
|
|
+ if (rc != 1) {
|
|
LOG_ERR("Failed to get random bytes");
|
|
goto error;
|
|
}
|
|
|
|
/*
|
|
- * This is the biggest buffer value, so it should always be sufficient.
|
|
+ * The seed value will be OAEP encrypted with a given L parameter.
|
|
*/
|
|
- unsigned char encoded[TPM2_MAX_DIGEST_BUFFER];
|
|
- return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded, mod_size,
|
|
- protection_seed->buffer, protection_seed->size, label, label_len,
|
|
- tpm2_openssl_md_from_tpmhalg(parent_name_alg), NULL);
|
|
- if (return_code != 1) {
|
|
- LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n");
|
|
- goto error;
|
|
- }
|
|
- BIGNUM* bne = BN_new();
|
|
- if (!bne) {
|
|
- LOG_ERR("BN_new for bne failed\n");
|
|
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
|
+ if (!ctx) {
|
|
+ LOG_ERR("Failed EVP_PKEY_CTX_new");
|
|
goto error;
|
|
}
|
|
- return_code = BN_set_word(bne, RSA_F4);
|
|
- if (return_code != 1) {
|
|
- LOG_ERR("BN_set_word failed\n");
|
|
- BN_free(bne);
|
|
+
|
|
+ rc = EVP_PKEY_encrypt_init(ctx);
|
|
+ if (rc <= 0) {
|
|
+ LOG_ERR("Failed EVP_PKEY_encrypt_init");
|
|
goto error;
|
|
}
|
|
- rsa = RSA_new();
|
|
- if (!rsa) {
|
|
- LOG_ERR("RSA_new failed\n");
|
|
- BN_free(bne);
|
|
+
|
|
+ rc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
|
|
+ if (rc <= 0) {
|
|
+ LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_padding");
|
|
goto error;
|
|
}
|
|
- return_code = RSA_generate_key_ex(rsa, mod_size_bits, bne, NULL);
|
|
- BN_free(bne);
|
|
- if (return_code != 1) {
|
|
- LOG_ERR("RSA_generate_key_ex failed\n");
|
|
+
|
|
+ rc = EVP_PKEY_CTX_set_rsa_oaep_md(ctx,
|
|
+ tpm2_openssl_md_from_tpmhalg(parent_name_alg));
|
|
+ if (rc <= 0) {
|
|
+ LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_oaep_md");
|
|
goto error;
|
|
}
|
|
- BIGNUM *n = BN_bin2bn(pub_modulus, mod_size, NULL);
|
|
- if (n == NULL) {
|
|
- LOG_ERR("BN_bin2bn failed\n");
|
|
+
|
|
+ // the library will take ownership of the label
|
|
+ char *newlabel = strdup((const char *)label);
|
|
+ if (newlabel == NULL) {
|
|
+ LOG_ERR("Failed to allocate label");
|
|
goto error;
|
|
}
|
|
- if (!RSA_set0_key(rsa, n, NULL, NULL)) {
|
|
- LOG_ERR("RSA_set0_key failed\n");
|
|
- BN_free(n);
|
|
+
|
|
+ rc = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, newlabel, label_len);
|
|
+ if (rc <= 0) {
|
|
+ LOG_ERR("Failed EVP_PKEY_CTX_set0_rsa_oaep_label");
|
|
+ free(newlabel);
|
|
goto error;
|
|
}
|
|
- // Encrypting
|
|
- encrypted_protection_seed->size = mod_size;
|
|
- return_code = RSA_public_encrypt(mod_size, encoded,
|
|
- encrypted_protection_seed->secret, rsa, RSA_NO_PADDING);
|
|
- if (return_code < 0) {
|
|
- LOG_ERR("Failed RSA_public_encrypt\n");
|
|
+
|
|
+ size_t outlen = sizeof(TPMU_ENCRYPTED_SECRET);
|
|
+ if (EVP_PKEY_encrypt(ctx, encrypted_protection_seed->secret, &outlen,
|
|
+ protection_seed->buffer, protection_seed->size) <= 0) {
|
|
+ LOG_ERR("Failed EVP_PKEY_encrypt\n");
|
|
goto error;
|
|
}
|
|
-
|
|
+ encrypted_protection_seed->size = outlen;
|
|
rval = true;
|
|
|
|
error:
|
|
- free(pub_modulus);
|
|
- RSA_free(rsa);
|
|
+ EVP_PKEY_CTX_free(ctx);
|
|
+ EVP_PKEY_free(pkey);
|
|
return rval;
|
|
}
|
|
|
|
--
|
|
2.31.1
|
|
|