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

Reply via email to