Hello community, here is the log from the commit of package libtpms for openSUSE:Factory checked in at 2020-11-23 15:48:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libtpms (Old) and /work/SRC/openSUSE:Factory/.libtpms.new.5913 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libtpms" Mon Nov 23 15:48:57 2020 rev:8 rq:850101 version:0.7.4 Changes: -------- --- /work/SRC/openSUSE:Factory/libtpms/libtpms.changes 2020-07-24 10:07:02.157997674 +0200 +++ /work/SRC/openSUSE:Factory/.libtpms.new.5913/libtpms.changes 2020-11-23 18:50:05.149343418 +0100 @@ -1,0 +2,10 @@ +Mon Nov 23 03:31:28 UTC 2020 - Gary Ching-Pang Lin <g...@suse.com> + +- Update to version 0.7.4 + * Addressed potential constant-time related issues in TPM 1.2 and + TPM 2 code + TPM 1.2: RSA decryption + TPM 2: EcSchnorr and EcSM2 signatures; Ecsda is handled by OpenSSL + * Fixed some compilation issues + +------------------------------------------------------------------- Old: ---- v0.7.3.tar.gz New: ---- v0.7.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libtpms.spec ++++++ --- /var/tmp/diff_new_pack.XQN9Ap/_old 2020-11-23 18:50:06.445344729 +0100 +++ /var/tmp/diff_new_pack.XQN9Ap/_new 2020-11-23 18:50:06.449344733 +0100 @@ -18,7 +18,7 @@ %define lname libtpms0 Name: libtpms -Version: 0.7.3 +Version: 0.7.4 Release: 0 Summary: Library providing Trusted Platform Module (TPM) functionality License: BSD-3-Clause ++++++ v0.7.3.tar.gz -> v0.7.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/.travis.yml new/libtpms-0.7.4/.travis.yml --- old/libtpms-0.7.3/.travis.yml 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/.travis.yml 2020-10-30 20:24:40.000000000 +0100 @@ -38,7 +38,7 @@ NPROC="nproc" - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2 --enable-test-coverage" TARGET="install" NPROC="nproc" - dist: xenial + dist: bionic before_script: - sudo pip install cpp-coveralls script: @@ -47,11 +47,15 @@ sudo make -j$(nproc) check && git clone https://github.com/stefanberger/swtpm.git && pushd swtpm && - sudo apt -y install devscripts equivs python-twisted libfuse-dev - libglib2.0-dev libgmp-dev expect libtasn1-dev socat findutils - tpm-tools gnutls-dev gnutls-bin && + sudo rm -rf /dev/tpm* && + sudo apt -y install devscripts equivs python3-twisted expect + libtasn1-dev socat findutils gnutls-dev gnutls-bin tss2 + python3-setuptools python3-cryptography python3-pip && + pip3 install --upgrade pip && + pip3 install --upgrade wheel && + pip3 install --upgrade cryptography && ./autogen.sh --with-gnutls --prefix=/usr && - export SWTPM_TEST_EXPENSIVE=1 && + export SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_IBMTSS2=1 && sudo make -j$(nproc) check && popd after_success: @@ -60,18 +64,22 @@ cpp-coveralls -b src -e tests -e swtpm --gcov-options '\-lp' - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2 --enable-test-coverage --disable-use-openssl-functions" TARGET="install" NPROC="nproc" - dist: xenial + dist: bionic script: ./autogen.sh ${CONFIG} && sudo make -j$(nproc) ${TARGET} && sudo make -j$(nproc) check && git clone https://github.com/stefanberger/swtpm.git && pushd swtpm && - sudo apt -y install devscripts equivs python-twisted libfuse-dev - libglib2.0-dev libgmp-dev expect libtasn1-dev socat findutils - tpm-tools gnutls-dev gnutls-bin && + sudo rm -rf /dev/tpm* && + sudo apt -y install devscripts equivs python3-twisted expect + libtasn1-dev socat findutils gnutls-dev gnutls-bin tss2 + python3-setuptools python3-cryptography python3-pip && + pip3 install --upgrade pip && + pip3 install --upgrade wheel && + pip3 install --upgrade cryptography && ./autogen.sh --with-gnutls --prefix=/usr && - export SWTPM_TEST_EXPENSIVE=1 && + export SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_IBMTSS2=1 && sudo make -j$(nproc) check && popd - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2" "TARGET=check" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/CHANGES new/libtpms-0.7.4/CHANGES --- old/libtpms-0.7.3/CHANGES 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/CHANGES 2020-10-30 20:24:40.000000000 +0100 @@ -1,5 +1,11 @@ CHANGES - changes for libtpms +version 0.7.4 + - Addressed potential constant-time related issues in TPM 1.2 and TPM 2 code + TPM 1.2: RSA decryption + TPM 2: EcSchnorr and EcSM2 signatures; Ecsda is handled by OpenSSL + - Fixed some compilation issues + version 0.7.3 - Fixed the set of PCRs belonging to the TCB group. This affects the pcrUpdateCounter in TPM2_Pcrread() responses, thus needs latest `swtpm` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/configure.ac new/libtpms-0.7.4/configure.ac --- old/libtpms-0.7.3/configure.ac 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/configure.ac 2020-10-30 20:24:40.000000000 +0100 @@ -3,7 +3,7 @@ # # See the LICENSE file for the license associated with this file. -AC_INIT([libtpms], [0.7.3]) +AC_INIT([libtpms], [0.7.4]) AC_PREREQ(2.12) AC_CONFIG_SRCDIR(Makefile.am) AC_CONFIG_AUX_DIR([.]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/debian/changelog new/libtpms-0.7.4/debian/changelog --- old/libtpms-0.7.3/debian/changelog 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/debian/changelog 2020-10-30 20:24:40.000000000 +0100 @@ -1,3 +1,7 @@ +litpmss (0.7.4) RELEASED; urgency=medium + + * Addressed potential constant-time issues in TPM 1.2 and TPM 2 code + libtpms (0.7.3-1) RELEASED; urgency=medium * Fixed set of PCRs belonging to TCB group diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/dist/libtpms.spec new/libtpms-0.7.4/dist/libtpms.spec --- old/libtpms-0.7.3/dist/libtpms.spec 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/dist/libtpms.spec 2020-10-30 20:24:40.000000000 +0100 @@ -1,7 +1,7 @@ # --- libtpm rpm-spec --- %define name libtpms -%define version 0.7.3 +%define version 0.7.4 %define release 0 # Valid crypto subsystems are 'freebl' and 'openssl' @@ -112,6 +112,9 @@ %postun -p /sbin/ldconfig %changelog +* Mon Oct 25 2020 Stefan Berger - 0.7.4-1 +- Addressed potential constant-time issues in TPM 1.2 and TPM 2 code + * Fri Jul 10 2020 Stefan Berger - 0.7.3-1 - Fixed set of PCRs belonging to TCB group diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/dist/libtpms.spec.in new/libtpms-0.7.4/dist/libtpms.spec.in --- old/libtpms-0.7.3/dist/libtpms.spec.in 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/dist/libtpms.spec.in 2020-10-30 20:24:40.000000000 +0100 @@ -112,6 +112,9 @@ %postun -p /sbin/ldconfig %changelog +* Mon Oct 25 2020 Stefan Berger - 0.7.4-1 +- Addressed potential constant-time issues in TPM 1.2 and TPM 2 code + * Fri Jul 10 2020 Stefan Berger - 0.7.3-1 - Fixed set of PCRs belonging to TCB group diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/include/libtpms/tpm_library.h new/libtpms-0.7.4/include/libtpms/tpm_library.h --- old/libtpms-0.7.3/include/libtpms/tpm_library.h 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/include/libtpms/tpm_library.h 2020-10-30 20:24:40.000000000 +0100 @@ -50,7 +50,7 @@ #define TPM_LIBRARY_VER_MAJOR 0 #define TPM_LIBRARY_VER_MINOR 7 -#define TPM_LIBRARY_VER_MICRO 3 +#define TPM_LIBRARY_VER_MICRO 4 #define TPM_LIBRARY_VERSION_GEN(MAJ, MIN, MICRO) \ (( MAJ << 16 ) | ( MIN << 8 ) | ( MICRO )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/Makefile.am new/libtpms-0.7.4/src/Makefile.am --- old/libtpms-0.7.3/src/Makefile.am 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/Makefile.am 2020-10-30 20:24:40.000000000 +0100 @@ -74,6 +74,7 @@ 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 @@ 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 \ @@ -510,6 +512,7 @@ tpm2/crypto/openssl/TpmToOsslSupport.c noinst_HEADERS += \ + tpm2/crypto/openssl/ConsttimeUtils.h \ tpm2/crypto/openssl/BnConvert_fp.h \ tpm2/crypto/openssl/BnMath_fp.h \ tpm2/crypto/openssl/BnMemory_fp.h \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm12/tpm_crypto.c new/libtpms-0.7.4/src/tpm12/tpm_crypto.c --- old/libtpms-0.7.3/src/tpm12/tpm_crypto.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm12/tpm_crypto.c 2020-10-30 20:24:40.000000000 +0100 @@ -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' }; @@ -539,6 +540,7 @@ (*rsa_pri_key)->n = n; (*rsa_pri_key)->e = e; (*rsa_pri_key)->d = d; + BN_set_flags(d, BN_FLG_CONSTTIME); // d is private #else int irc = RSA_set0_key(*rsa_pri_key, n, e, d); if (irc != 1) { @@ -550,6 +552,7 @@ 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'. @@ -658,10 +661,137 @@ 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'. */ +#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added + TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ size_t encrypt_data_size, /* size of encrypted data buffer */ TPM_ENC_SCHEME encScheme, @@ -752,6 +882,115 @@ return rc; } +#else // libtpms added begin + +TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ + size_t encrypt_data_size, /* size of encrypted data buffer */ + TPM_ENC_SCHEME encScheme, + const unsigned char *decrypt_data, /* decrypted data */ + size_t decrypt_data_size, + unsigned char *narr, /* public modulus */ + uint32_t nbytes, + unsigned char *earr, /* public exponent */ + uint32_t ebytes) +{ + 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; + + printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); + + /* construct the OpenSSL private key object */ + if (rc == 0) { + rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes, + NULL, /* private exponent */ + 0); + } + + if (rc == 0) { + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == 0) { + printf("TPM_RSAqPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); + rc = TPM_FAIL; + } + } + if (rc == 0) { + if (EVP_PKEY_encrypt_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_RSAPublicEncrypt: Error in setting up encrypt 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_RSAPublicEncrypt: 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_RSAPublicEncrypt: 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_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESPKCSv15\n"); + rc = TPM_FAIL; + } + } + break; + default: + if (rc == 0) { + printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); + rc = TPM_INAPPROPRIATE_ENC; + } + } + } + + if (rc == 0) { + outlen = encrypt_data_size; + if (EVP_PKEY_encrypt(ctx, encrypt_data, &outlen, + decrypt_data, decrypt_data_size) <= 0) { + printf("TPM_RSAPublicEncrypt: EVP_PKEY_encrypt failed\n"); + rc = TPM_ENCRYPT_ERROR; + } + } + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + TPM_Free(label); + + return rc; +} + +#endif // libtpms added end + #if 0 /* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. @@ -830,6 +1069,15 @@ 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most 'signature_size'. signature must point to RSA_size(rsa) bytes of memory. */ +/* Note regarding conversion to EVP_PKEY_sign for the purpose of constant-timeness: + + - TPM_SS_RSASSAPKCS1v15_SHA1: + EVP_PKEY_sign() will call pkey_rsa_sign() which in turn will call RSA_sign() for + RSA_PKCS1_PADDING. This is the same as we do here. + - TPM_SS_RSASSAPKCS1v15_DER: + EVP_PKEY_sign() must not have a message digest since none of the padding choices calls + RSA_padding_add_PKCS1_type_1(), so we would have to do the padding again ourselves. +*/ TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ @@ -1150,6 +1398,8 @@ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&p, parr, pbytes); /* freed @3 */ + if (p) + BN_set_flags(p, BN_FLG_CONSTTIME); // p is private } /* calculate q = n/p */ if (rc == 0) { @@ -1158,7 +1408,8 @@ printf("TPM_RSAGetPrivateKey: Error in BN_div()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; - } + } else + BN_set_flags(q, BN_FLG_CONSTTIME); // q is private } /* remainder should be zero */ if (rc == 0) { @@ -1193,7 +1444,8 @@ printf("TPM_RSAGetPrivateKey: Error in BN_mul()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; - } + } else + BN_set_flags(r2, BN_FLG_CONSTTIME); // r2 is private } /* calculate d = multiplicative inverse e mod r0 */ if (rc == 0) { @@ -1543,6 +1795,7 @@ */ if (rc == 0) { printf(" TPM_BN_mod_exp: Calculate mod_exp\n"); + BN_set_flags(pBignum, BN_FLG_CONSTTIME); // p may be private irc = BN_mod_exp(rBignum, aBignum, pBignum, nBignum, ctx); if (irc != 1) { printf("TPM_BN_mod_exp: Error performing BN_mod_exp()\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm12/tpm_nvram.c new/libtpms-0.7.4/src/tpm12/tpm_nvram.c --- old/libtpms-0.7.3/src/tpm12/tpm_nvram.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm12/tpm_nvram.c 2020-10-30 20:24:40.000000000 +0100 @@ -1997,7 +1997,7 @@ TPM_BOOL done = FALSE; TPM_BOOL dir = FALSE; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ - TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; + TPM_NV_DATA_SENSITIVE *d1NvdataSensitive = NULL; uint32_t s1Last; TPM_BOOL physicalPresence; TPM_BOOL isGPIO = FALSE; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm12/tpm_openssl_helpers.c new/libtpms-0.7.4/src/tpm12/tpm_openssl_helpers.c --- old/libtpms-0.7.3/src/tpm12/tpm_openssl_helpers.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libtpms-0.7.4/src/tpm12/tpm_openssl_helpers.c 2020-10-30 20:24:40.000000000 +0100 @@ -0,0 +1,135 @@ +/********************************************************************************/ +/* */ +/* 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 <openssl/evp.h> +#include <openssl/rsa.h> +#include <openssl/bn.h> + +#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) { + if (darr != NULL) { + 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm12/tpm_openssl_helpers.h new/libtpms-0.7.4/src/tpm12/tpm_openssl_helpers.h --- old/libtpms-0.7.3/src/tpm12/tpm_openssl_helpers.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libtpms-0.7.4/src/tpm12/tpm_openssl_helpers.h 2020-10-30 20:24:40.000000000 +0100 @@ -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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/BnMath.c new/libtpms-0.7.4/src/tpm2/BnMath.c --- old/libtpms-0.7.3/src/tpm2/BnMath.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/BnMath.c 2020-10-30 20:24:40.000000000 +0100 @@ -552,3 +552,81 @@ } return TRUE; } + +// libtpms added begin + +// This version of BnSizeInBits skips any leading zero bytes in bigConst +// and thus calculates the bits that OpenSSL will work with after truncating +// the leading zeros +static LIB_EXPORT unsigned +BnSizeInBitsSkipLeadingZeros( + bigConst n + ) +{ + int firstByte; + unsigned bitSize = BnSizeInBits(n); + crypt_uword_t i; + + if (bitSize <= 8) + return bitSize; + + // search for the first limb that is non-zero + for (i = 0; i < n->size; i++) { + if (n->d[i] != 0) + break; + } + if (i >= n->size) + return 0; // should never happen + + // get the first byte in this limb that is non-zero + firstByte = (RADIX_BITS - 1 - Msb(n->d[i])) >> 3; + + return bitSize - i * sizeof(n->d[0]) - (firstByte << 3); +} + + +/* This is a version of BnGenerateRandomInRange that ensures that the upper most + byte is non-zero, so that the number will not be shortened and subsequent operations + will not have a timing-sidechannel + */ +LIB_EXPORT BOOL +BnGenerateRandomInRangeAllBytes( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ) +{ + BOOL OK; + int repeats = 0; + int maxRepeats; + unsigned requestedBits; + unsigned requestedBytes; + unsigned numBytes; + + if (rand) + return BnGenerateRandomInRange(dest, limit, rand); + + // a 'limit' like 'BN_P638_n' has leading zeros and we only need 73 bytes not 80 + requestedBits = BnSizeInBitsSkipLeadingZeros(limit); + requestedBytes = BITS_TO_BYTES(requestedBits); + maxRepeats = 8; + if (requestedBits & 7) + maxRepeats += (9 - (requestedBits & 7)); + + while (true) { + OK = BnGenerateRandomInRange(dest, limit, rand); + if (!OK) + break; + if (repeats < maxRepeats) { + numBytes = BITS_TO_BYTES(BnSizeInBitsSkipLeadingZeros(dest)); + if (numBytes < requestedBytes) { + repeats++; + continue; + } + } + break; + } + + return OK; +} +// libtpms added end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/Marshal.c new/libtpms-0.7.4/src/tpm2/Marshal.c --- old/libtpms-0.7.3/src/tpm2/Marshal.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/Marshal.c 2020-10-30 20:24:40.000000000 +0100 @@ -2198,7 +2198,7 @@ TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; - BYTE *sizePtr; + BYTE *sizePtr = NULL; // libtpms added for s390x on Fedora 32 if (buffer != NULL) { sizePtr = *buffer; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/Marshal_fp.h new/libtpms-0.7.4/src/tpm2/Marshal_fp.h --- old/libtpms-0.7.3/src/tpm2/Marshal_fp.h 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/Marshal_fp.h 2020-10-30 20:24:40.000000000 +0100 @@ -228,6 +228,8 @@ TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size); UINT16 TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 // libtpms added + TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 @@ -262,6 +264,8 @@ TPMS_SIG_SCHEME_ECSCHNORR_Marshal(TPMS_SIG_SCHEME_ECSCHNORR *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_ECDAA_Marshal(TPMS_SIG_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size); + UINT16 // libtpms added + TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP *source, BYTE **buffer, INT32 *size); UINT16 @@ -322,6 +326,8 @@ TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA *source, BYTE **buffer, INT32 *size); + UINT16 // libtpms added + TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECSCHNORR_Marshal(TPMS_SIGNATURE_ECSCHNORR *source, BYTE **buffer, INT32 *size); UINT16 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/CryptEccMain_fp.h new/libtpms-0.7.4/src/tpm2/crypto/CryptEccMain_fp.h --- old/libtpms-0.7.3/src/tpm2/crypto/CryptEccMain_fp.h 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/CryptEccMain_fp.h 2020-10-30 20:24:40.000000000 +0100 @@ -169,6 +169,8 @@ const ECC_CURVE_DATA *C, // IN: curve for which the private key #if USE_OPENSSL_FUNCTIONS_EC const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL + BOOL noLeadingZeros, // IN: require that all bytes in the private key be set + // result may not have leading zero bytes #endif // needs to be appropriate RAND_STATE *rand // IN: state for DRBG diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/BnMath_fp.h new/libtpms-0.7.4/src/tpm2/crypto/openssl/BnMath_fp.h --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/BnMath_fp.h 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/BnMath_fp.h 2020-10-30 20:24:40.000000000 +0100 @@ -151,6 +151,13 @@ bigConst limit, RAND_STATE *rand ); - +// libtpms added begin +LIB_EXPORT BOOL +BnGenerateRandomInRangeAllBytes( + bigNum dest, + bigConst limit, + RAND_STATE *rand + ); +// libtpms added end #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/ConsttimeUtils.h new/libtpms-0.7.4/src/tpm2/crypto/openssl/ConsttimeUtils.h --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/ConsttimeUtils.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/ConsttimeUtils.h 2020-10-30 20:24:40.000000000 +0100 @@ -0,0 +1,117 @@ +/********************************************************************************/ +/* */ +/* Constant time debugging helper functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (ad...@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2020 */ +/* */ +/********************************************************************************/ + +#ifndef CONSTTIME_UTILS_H +#define CONSTTIME_UTILS_H + +#include <assert.h> +#include <stdio.h> + +#include "BnValues.h" + +#include <openssl/bn.h> + +static __inline__ unsigned long long rdtsc() { + unsigned long h, l; + + __asm__ __volatile__ ("rdtsc" : "=a"(l), "=d"(h)); + + return (unsigned long long)l | + ((unsigned long long)h << 32 ); +} + +// Make sure that the given BIGNUM has the given number of expected bytes. +// Skip over any leading zeros the BIGNUM may have. +static inline void assert_ossl_num_bytes(const BIGNUM *a, + unsigned int num_bytes, + int verbose, + const char *caller) { + unsigned char buffer[LARGEST_NUMBER] = { 0, }; + int len, i; + + len = BN_bn2bin(a, buffer); + for (i = 0; i < len; i++) { + if (buffer[i]) + break; + } + len -= i; + if (num_bytes != (unsigned int)len) { + printf("%s: Expected %u bytes but found %d (caller: %s)\n", __func__, num_bytes, len, caller); + } else { + if (verbose) + printf("%s: check passed; num_bytes = %d (caller: %s)\n",__func__, num_bytes, caller); + } + assert(num_bytes == (unsigned int)len); +} + +// Make sure that the bigNum has the expected number of bytes after it was +// converted to an OpenSSL BIGNUM. +static inline void assert_bn_ossl_num_bytes(bigNum tpmb, + unsigned int num_bytes, + int verbose, + const char *caller) { + BIG_INITIALIZED(osslb, tpmb); + + assert_ossl_num_bytes(osslb, num_bytes, verbose, caller); + + BN_free(osslb); +} + +#endif /* CONSTTIME_UTILS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/CryptEccMain.c new/libtpms-0.7.4/src/tpm2/crypto/openssl/CryptEccMain.c --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/CryptEccMain.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/CryptEccMain.c 2020-10-30 20:24:40.000000000 +0100 @@ -575,6 +575,8 @@ bigNum dOut, // OUT: the qualified random value const ECC_CURVE_DATA *C, // IN: curve for which the private key const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL + BOOL noLeadingZeros, // IN: require that all bytes in the private key be set + // result may not have leading zero bytes // needs to be appropriate RAND_STATE *rand // IN: state for DRBG ) @@ -583,11 +585,16 @@ BOOL OK; UINT32 orderBits = BnSizeInBits(order); UINT32 orderBytes = BITS_TO_BYTES(orderBits); + UINT32 requestedBits = 0; BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); BN_VAR(nMinus1, MAX_ECC_KEY_BITS); - if (rand == NULL) - return OpenSSLEccGetPrivate(dOut, G); + if (rand == NULL) { + if (noLeadingZeros) + requestedBits = orderBits; + + return OpenSSLEccGetPrivate(dOut, G, requestedBits); + } // OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); @@ -600,6 +607,8 @@ /* 10.2.11.2.21 BnEccGenerateKeyPair() */ /* This function gets a private scalar from the source of random bits and does the point multiply to get the public key. */ +#if !USE_OPENSSL_FUNCTIONS_EC // libtpms added + BOOL BnEccGenerateKeyPair( bigNum bnD, // OUT: private scalar @@ -610,11 +619,7 @@ { BOOL OK = FALSE; // Get a private scalar -#if USE_OPENSSL_FUNCTIONS_EC // libtpms added beging - OK = BnEccGetPrivate(bnD, AccessCurveData(E), E->G, rand); -#else // libtpms added end OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand); -#endif // libtpms added // Do a point multiply OK = OK && BnEccModMult(ecQ, NULL, bnD, E); if(!OK) @@ -623,6 +628,54 @@ BnSetWord(ecQ->z, 1); return OK; } + +#else // libtpms added begin + +/* In this version of BnEccGenerateKeyPair we take a dual approach to constant + time requirements: For curves whose order is at the byte boundary, e.g. + NIST P224/P256/P384, we make sure that bnD has all bytes set (no leading zeros) + so that OpenSSL BIGNUM code will not reduce the number of bytes and the + subsequent BnEccModMult() would run faster for a shoter value. For all other + curves whose order is not at the byte boundary, e.g. NIST P521, we simply + always add the order of the curve to bnD and call BnEccModMult() with the + result bnD1, which leads to the same result. */ +BOOL +BnEccGenerateKeyPair( + bigNum bnD, // OUT: private scalar + bn_point_t *ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE *rand // IN: DRBG state to use + ) +{ + BOOL OK = FALSE; + bigConst order = CurveGetOrder(AccessCurveData(E)); + UINT32 orderBits = BnSizeInBits(order); + BOOL atByteBoundary = (orderBits & 7) == 0; + BOOL noLeadingZeros = atByteBoundary; + ECC_NUM(bnD1); + + // We request that bnD not have leading zeros if it is at byte-boundary, + // like for example it is the case for NIST P256. + OK = BnEccGetPrivate(bnD, AccessCurveData(E), E->G, noLeadingZeros, rand); + if (!atByteBoundary) { + // for NIST P521 we can add the order to bnD to ensure we have + // a constant amount of bytes; the result is the same as if we + // were doing the BnEccModMult() calculation with bnD. + OK = OK && BnAdd(bnD1, bnD, order); + OK = OK && BnEccModMult(ecQ, NULL, bnD1, E); + } else { + OK = OK && BnEccModMult(ecQ, NULL, bnD, E); + } + + if(!OK) + BnSetWord(ecQ->z, 0); + else + BnSetWord(ecQ->z, 1); + return OK; +} + +#endif // libtpms added end + /* 10.2.12.2.21 CryptEccNewKeyPair */ /* This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the key will be discarded */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/CryptEccSignature.c new/libtpms-0.7.4/src/tpm2/crypto/openssl/CryptEccSignature.c --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/CryptEccSignature.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/CryptEccSignature.c 2020-10-30 20:24:40.000000000 +0100 @@ -303,7 +303,7 @@ // generate nonceK such that 0 < nonceK < n // use bnT as a temp. #if USE_OPENSSL_FUNCTIONS_EC // libtpms added begin - if(!BnEccGetPrivate(bnT, AccessCurveData(E), E->G, rand)) + if(!BnEccGetPrivate(bnT, AccessCurveData(E), E->G, false, rand)) #else // libtpms added end if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand)) #endif // libtpms added @@ -323,6 +323,7 @@ CryptDigestUpdate2B(&state, &digest->b); CryptHashEnd2B(&state, &T.b); BnFrom2B(bnT, &T.b); + // libtpms: Note: T is NOT a concern for constant-timeness // Watch out for the name collisions in this call!! retVal = BnSchnorrSign(bnS, bnR, bnT, bnD, AccessCurveData(E)->order); @@ -420,6 +421,7 @@ SchnorrReduce(e, order); // Convert hash to number BnFrom2B(bnR, e); + // libtpms: Note: e is NOT a concern for constant-timeness // Do the Schnorr computation retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C)); } while(retVal == TPM_RC_NO_RESULT); @@ -470,6 +472,12 @@ POINT(Q1); bigConst order = (E != NULL) ? CurveGetOrder(AccessCurveData(E)) : NULL; +// libtpms added begin + UINT32 orderBits = BnSizeInBits(order); + BOOL atByteBoundary = (orderBits & 7) == 0; + ECC_NUM(bnK1); +// libtpms added end + // #ifdef _SM2_SIGN_DEBUG BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1" @@ -482,16 +490,36 @@ loop: { // Get a random number 0 < k < n - BnGenerateRandomInRange(bnK, order, rand); + // libtpms modified begin + // + // We take a dual approach here. One for curves whose order is not at + // the byte boundary, e.g. NIST P521, we get a random number bnK and add + // the order to that number to have bnK1. This will not spill over into + // a new byte and we can then use bnK1 to do the do the BnEccModMult + // with a constant number of bytes. For curves whose order is at the + // byte boundary we require that the random number bnK comes back with + // a requested number of bytes. + if (!atByteBoundary) { + BnGenerateRandomInRange(bnK, order, rand); + BnAdd(bnK1, bnK, order); #ifdef _SM2_SIGN_DEBUG - BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F" - "C176D925DD72B727260DBAAE1FB2F96F"); + BnFromHex(bnK1, "6CB28D99385C175C94F94E934817663F" + "C176D925DD72B727260DBAAE1FB2F96F"); #endif - // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according - // to details specified in 4.2.7 in Part 1 of this document, transform the - // data type of x1 into an integer; - if(!BnEccModMult(Q1, NULL, bnK, E)) - goto loop; + // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according + // to details specified in 4.2.7 in Part 1 of this document, transform the + // data type of x1 into an integer; + if(!BnEccModMult(Q1, NULL, bnK1, E)) + goto loop; + } else { + BnGenerateRandomInRangeAllBytes(bnK, order, rand); +#ifdef _SM2_SIGN_DEBUG + BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F" + "C176D925DD72B727260DBAAE1FB2F96F"); +#endif + if(!BnEccModMult(Q1, NULL, bnK, E)) + goto loop; + } // libtpms modified end // A5: Figure out r = (e + x1) mod n, BnAdd(bnR, bnE, Q1->x); BnMod(bnR, order); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/Helpers.c new/libtpms-0.7.4/src/tpm2/crypto/openssl/Helpers.c --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/Helpers.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/Helpers.c 2020-10-30 20:24:40.000000000 +0100 @@ -210,12 +210,17 @@ BOOL OpenSSLEccGetPrivate( bigNum dOut, // OUT: the qualified random value - const EC_GROUP *G // IN: the EC_GROUP to use + const EC_GROUP *G, // IN: the EC_GROUP to use + const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits ) { BOOL OK = FALSE; const BIGNUM *D; EC_KEY *eckey = EC_KEY_new(); + UINT32 requestedBytes = BITS_TO_BYTES(requestedBits); + int repeats = 0; + int maxRepeats; + int numBytes; pAssert(G != NULL); @@ -225,10 +230,31 @@ if (EC_KEY_set_group(eckey, G) != 1) goto Exit; - if (EC_KEY_generate_key(eckey) == 1) { - OK = TRUE; - D = EC_KEY_get0_private_key(eckey); - OsslToTpmBn(dOut, D); + maxRepeats = 8; + // non-byte boundary order'ed curves, like NIST P521, need more loops to + // have a result with topmost byte != 0 + if (requestedBits & 7) + maxRepeats += (9 - (requestedBits & 7)); + + while (true) { + if (EC_KEY_generate_key(eckey) == 1) { + D = EC_KEY_get0_private_key(eckey); + // if we need a certain amount of bytes and we are below a threshold + // of loops, check the number of bytes we have, otherwise take the + // result + if ((requestedBytes != 0) && (repeats < maxRepeats)) { + numBytes = BN_num_bytes(D); + if ((int)requestedBytes != numBytes) { + // result does not have enough bytes + repeats++; + continue; + } + // result is sufficient + } + OK = TRUE; + OsslToTpmBn(dOut, D); + } + break; } Exit: @@ -305,6 +331,7 @@ pOK = pOK && BN_sub(phi, phi, Q); pOK = pOK && BN_add_word(phi, 1); // Compute the multiplicative inverse d = 1/e mod Phi + BN_set_flags(phi, BN_FLG_CONSTTIME); pOK = pOK && (*D = BN_mod_inverse(NULL, E, phi, ctx)) != NULL; } BN_CTX_free(ctx); @@ -398,9 +425,11 @@ RSA_get0_key(key, &N, &E, NULL); /* Q = N/P; no remainder */ + BN_set_flags(P, BN_FLG_CONSTTIME); // P is secret BN_div(Q, Qr, N, P, ctx); if(!BN_is_zero(Qr)) ERROR_RETURN(TPM_RC_BINDING); + BN_set_flags(Q, BN_FLG_CONSTTIME); // Q is secret // TODO(stefanb): consider caching D in the OBJECT if (ComputePrivateExponentD(P, Q, E, N, &D) == FALSE || diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/Helpers_fp.h new/libtpms-0.7.4/src/tpm2/crypto/openssl/Helpers_fp.h --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/Helpers_fp.h 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/Helpers_fp.h 2020-10-30 20:24:40.000000000 +0100 @@ -85,7 +85,8 @@ #if USE_OPENSSL_FUNCTIONS_EC BOOL OpenSSLEccGetPrivate( bigNum dOut, // OUT: the qualified random value - const EC_GROUP *G // IN: the EC_GROUP to use + const EC_GROUP *G, // IN: the EC_GROUP to use + const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits ); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/TpmToOsslMath.c new/libtpms-0.7.4/src/tpm2/crypto/openssl/TpmToOsslMath.c --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/TpmToOsslMath.c 2020-07-09 20:26:39.000000000 +0200 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/TpmToOsslMath.c 2020-10-30 20:24:40.000000000 +0100 @@ -330,6 +330,7 @@ BIG_INITIALIZED(bn2, number2); BOOL OK; pAssert(gcd != NULL); + BN_set_flags(bn1, BN_FLG_CONSTTIME); // number1 is secret prime number OK = BN_gcd(bnGcd, bn1, bn2, CTX); if(OK) { @@ -363,6 +364,7 @@ BIG_INITIALIZED(bnM, modulus); BOOL OK; // + BN_set_flags(bnE, BN_FLG_CONSTTIME); // exponent may be private OK = BN_mod_exp(bnResult, bnN, bnE, bnM, CTX); if(OK) { @@ -392,6 +394,7 @@ BIG_INITIALIZED(bnN, number); BIG_INITIALIZED(bnM, modulus); BOOL OK; + BN_set_flags(bnN, BN_FLG_CONSTTIME); // number may be private OK = (BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL); if(OK) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtpms-0.7.3/src/tpm2/crypto/openssl/consttime.txt new/libtpms-0.7.4/src/tpm2/crypto/openssl/consttime.txt --- old/libtpms-0.7.3/src/tpm2/crypto/openssl/consttime.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/libtpms-0.7.4/src/tpm2/crypto/openssl/consttime.txt 2020-10-30 20:24:40.000000000 +0100 @@ -0,0 +1,74 @@ +The following OpenSSL public BIGNUM functions check for the BN_FLG_CONSTTIME: + +bn_blind.c: + BN_BLINDING_new() + +bn_exp.c: + BN_exp : must not be set for input bignums +! BN_mod_exp : SHOULD be set for any one of input bignums (only) if m is odd + BN_mod_exp_recp: must NOT be set for input bignums + BN_mod_exp_mont: SHOULD be set for any one of input bignums + BN_mod_exp_mont_word: must NOT be set for input bignums + BN_mod_exp_simple: must NOT bet set for input bignums + +bn_gcd.c: +! BN_mod_inverse: SHOULD be set for any one of input bignums + +bn_lib: + BN_num_bits +! BN_copy + +bn_mont.c: + BN_MONT_CTX_set + +bn.h: +! BN_num_bytes: Calls BN_num_bits + + +Relevant files and functions in the files: +Helpers.c + ComputePrivateExponentD: + - BN_dup: -> BN_copy: YES, BN_FLG_CONSTTIME set by caller on P and Q + - BN_sub: no + - BN_add_word: no + - BN_mod_inverse: YES, DONE + InitOpenSSLRSAPublicKey: + - BN_set_word: no (?) + - BN_bin2bn: no + InitOpenSSLRSAPrivateKey: + - BN_bin2bn: no + - BN_div: -> BN_copy: YES, DONE + - BN_is_zero: no + +TpmToOsslMath: + OsslToTpmBn: + - BN_num_bytes: need not + - BN_bn2bin: -> BN_num_bytes: need not + BigInitialized: + - BN_bin2bn: no + BnModMult: + - BN_mul: no + - BN_div: -> BN_copy: should ? + BnMult: + - BN_mul: no + BnDiv: + - BN_div: -> BN_copy: should ? + BnGcd: + - BN_gcd: -> BN_copy, BN_num_bits: YES, DONE + BnModExp: + - BN_mod_exp: YES, DONE + BnModInverse: + - BN_mod_inverse: YES, DONE + + +Elliptic curve signing : + +CryptEccMain.c: + BnEccGenerateKeyPair: + - BnEccModMult: YES, DONE (we have control over random number bnD) + called by BnSignEcSchnorr + called by BnSignEcdsa (if OpenSSL function not used) + +CryptEccSignature.c: + BnEccSignSM2: + - BnEccModMult: YES, DONE (we have control over random number bnK) _______________________________________________ openSUSE Commits mailing list -- commit@lists.opensuse.org To unsubscribe, email commit-le...@lists.opensuse.org List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette List Archives: https://lists.opensuse.org/archives/list/commit@lists.opensuse.org