diff --git a/src/Makefile.am b/src/Makefile.am index 670afbfc..ad3e105b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ libtpms_tpm12_la_SOURCES = \ tpm12/tpm_nonce.c \ tpm12/tpm_nvfile.c \ tpm12/tpm_nvram.c \ + tpm12/tpm_openssl_helpers.c \ tpm12/tpm_owner.c \ tpm12/tpm_pcr.c \ tpm12/tpm_permanent.c \ @@ -120,6 +121,7 @@ noinst_HEADERS = \ tpm12/tpm_nvfile.h \ tpm12/tpm_nvram_const.h \ tpm12/tpm_nvram.h \ + tpm12/tpm_openssl_helpers.h \ tpm12/tpm_owner.h \ tpm12/tpm_pcr.h \ tpm12/tpm_permanent.h \ diff --git a/src/tpm12/tpm_crypto.c b/src/tpm12/tpm_crypto.c index 11a3b236..86444a2d 100644 --- a/src/tpm12/tpm_crypto.c +++ b/src/tpm12/tpm_crypto.c @@ -61,6 +61,7 @@ #include "tpm_crypto.h" +#include "tpm_openssl_helpers.h" // libtpms added /* The TPM OAEP encoding parameter */ static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; @@ -551,6 +552,7 @@ static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, /* freed by cal return rc; } +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added /* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. @@ -659,6 +661,131 @@ TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted dat return rc; } +#else // libtpms added begin + +TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ + uint32_t *decrypt_data_length, /* length of data put into + decrypt_data */ + size_t decrypt_data_size, /* size of decrypt_data buffer */ + TPM_ENC_SCHEME encScheme, /* encryption scheme */ + unsigned char *encrypt_data, /* encrypted data */ + uint32_t encrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; + unsigned char *label = NULL; + size_t outlen; + unsigned char buffer[(TPM_RSA_KEY_LENGTH_MAX + 7) / 8]; + + printf(" TPM_RSAPrivateDecrypt:\n"); + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + darr, /* private exponent */ + dbytes); + } + + if (rc == 0) { + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == 0) { + printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); + rc = TPM_FAIL; + } + } + + if (rc == 0) { + switch (encScheme) { + case TPM_ES_RSAESOAEP_SHA1_MGF1: + if (rc == 0) { + md = EVP_get_digestbyname("sha1"); + if (md == NULL || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); + if (rc) { + printf("TPM_RSAPrivateDecrypt: TPM_Malloc failed\n"); + } + } + if (rc == 0) { + memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { + printf("TPM_RSAPrivateDecrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); + rc = TPM_FAIL; + } + if (rc == 0) { + label = NULL; + } + } + break; + case TPM_ES_RSAESPKCSv15: + if (rc == 0) { + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESPKCSv15\n"); + rc = TPM_FAIL; + } + } + break; + default: + if (rc == 0) { + printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + } + + if (rc == 0) { + outlen = sizeof(buffer); + if (EVP_PKEY_decrypt(ctx, buffer, &outlen, + encrypt_data, encrypt_data_size) <= 0) { + printf("TPM_RSAPrivateDecrypt: EVP_PKEY_decrypt failed\n"); + rc = TPM_DECRYPT_ERROR; + } + if (rc == 0) { + if (outlen > decrypt_data_size) { + printf("TPM_RSAPrivateDecrypt: Error, decrypt_data_size %u too small for message size %u\n", + decrypt_data_size, outlen); + rc = TPM_DECRYPT_ERROR; + } + } + if (rc == 0) { + *decrypt_data_length = (uint32_t)outlen; + memcpy(decrypt_data, buffer, outlen); + TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data); + } + } + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + TPM_Free(label); + + return rc; +} + +#endif // libtpms added end + /* TPM_RSAPublicEncrypt() pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the public key 'n, e'. */ diff --git a/src/tpm12/tpm_openssl_helpers.c b/src/tpm12/tpm_openssl_helpers.c new file mode 100644 index 00000000..89188fbb --- /dev/null +++ b/src/tpm12/tpm_openssl_helpers.c @@ -0,0 +1,133 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2020. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#include +#include +#include + +#include "tpm_debug.h" +#include "tpm_error.h" +#include "tpm_openssl_helpers.h" + +#include "tpm_crypto.h" + +#if USE_OPENSSL_FUNCTIONS_RSA + +TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes) +{ + TPM_RESULT rc = 0; + int irc; + BIGNUM * n = NULL; + BIGNUM * e = NULL; + BIGNUM * d = NULL; + RSA * rsakey = NULL; + + /* sanity check for the free */ + if (rc == 0) { + if (*pkey != NULL) { + printf("TPM_RSAGeneratePrivateToken: Error (fatal), pkey %p should be NULL\n", + *pkey); + rc = TPM_FAIL; + } + } + /* construct the OpenSSL private key object */ + if (rc == 0) { + *pkey = EVP_PKEY_new(); /* freed by caller */ + if (*pkey == NULL) { + printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ + } + if (rc == 0) { + rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ + } + if (rc == 0) { + rsakey = RSA_new(); + if (rsakey == NULL) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + irc = RSA_set0_key(rsakey, n, e, d); + if (irc != 1) { + printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); + rc = TPM_FAIL; + } else { + n = NULL; + e = NULL; + d = NULL; + } + } + if (rc == 0) { + RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); + irc = EVP_PKEY_assign_RSA(*pkey, rsakey); + if (irc == 0) { + printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_assign_RSA()\n"); + rc = TPM_FAIL; + } else { + rsakey = NULL; + } + } + + if (rc != 0) { + EVP_PKEY_free(*pkey); + *pkey = NULL; + RSA_free(rsakey); + BN_free(n); + BN_free(e); + BN_clear_free(d); + } + + return rc; +} + +#endif + diff --git a/src/tpm12/tpm_openssl_helpers.h b/src/tpm12/tpm_openssl_helpers.h new file mode 100644 index 00000000..330fd98b --- /dev/null +++ b/src/tpm12/tpm_openssl_helpers.h @@ -0,0 +1,50 @@ +/********************************************************************************/ +/* */ +/* OpenSSL helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* (c) Copyright IBM Corporation 2020. */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* */ +/* Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the names of the IBM Corporation nor the names of its */ +/* contributors may be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/********************************************************************************/ + +#ifndef TPM_OPENSSL_HELPERS_H +#define TPM_OPENSSL_HELPERS_H + +TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes, + unsigned char *darr, /* private exponent */ + uint32_t dbytes); + +#endif