Blame SOURCES/0017-openssl-Reimplement-RSA-OAEP-encryption-using-EVP-fu.patch

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