summaryrefslogtreecommitdiffstats
path: root/src/tpm2/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm2/crypto')
-rw-r--r--src/tpm2/crypto/CryptCmac_fp.h86
-rw-r--r--src/tpm2/crypto/CryptDes_fp.h82
-rw-r--r--src/tpm2/crypto/CryptEcc.h103
-rw-r--r--src/tpm2/crypto/CryptEccCrypt_fp.h67
-rw-r--r--src/tpm2/crypto/CryptEccKeyExchange_fp.h78
-rw-r--r--src/tpm2/crypto/CryptEccMain_fp.h232
-rw-r--r--src/tpm2/crypto/CryptEccSignature_fp.h111
-rw-r--r--src/tpm2/crypto/CryptHash.h343
-rw-r--r--src/tpm2/crypto/CryptHash_fp.h219
-rw-r--r--src/tpm2/crypto/CryptPrimeSieve_fp.h101
-rw-r--r--src/tpm2/crypto/CryptPrime_fp.h104
-rw-r--r--src/tpm2/crypto/CryptRand.h193
-rw-r--r--src/tpm2/crypto/CryptRand_fp.h158
-rw-r--r--src/tpm2/crypto/CryptRsa.h99
-rw-r--r--src/tpm2/crypto/CryptRsa_fp.h139
-rw-r--r--src/tpm2/crypto/CryptSelfTest_fp.h87
-rw-r--r--src/tpm2/crypto/CryptSmac_fp.h98
-rw-r--r--src/tpm2/crypto/CryptSym.h142
-rw-r--r--src/tpm2/crypto/CryptSym_fp.h111
-rw-r--r--src/tpm2/crypto/CryptTest.h93
-rw-r--r--src/tpm2/crypto/CryptUtil_fp.h232
-rw-r--r--src/tpm2/crypto/openssl/BnConvert_fp.h108
-rw-r--r--src/tpm2/crypto/openssl/BnMath_fp.h163
-rw-r--r--src/tpm2/crypto/openssl/BnMemory_fp.h108
-rw-r--r--src/tpm2/crypto/openssl/BnValues.h329
-rw-r--r--src/tpm2/crypto/openssl/ConsttimeUtils.h117
-rw-r--r--src/tpm2/crypto/openssl/CryptCmac.c210
-rw-r--r--src/tpm2/crypto/openssl/CryptDes.c189
-rw-r--r--src/tpm2/crypto/openssl/CryptEccKeyExchange.c373
-rw-r--r--src/tpm2/crypto/openssl/CryptEccMain.c866
-rw-r--r--src/tpm2/crypto/openssl/CryptEccSignature.c1043
-rw-r--r--src/tpm2/crypto/openssl/CryptHash.c871
-rw-r--r--src/tpm2/crypto/openssl/CryptPrime.c440
-rw-r--r--src/tpm2/crypto/openssl/CryptPrimeSieve.c554
-rw-r--r--src/tpm2/crypto/openssl/CryptRand.c881
-rw-r--r--src/tpm2/crypto/openssl/CryptRsa.c1634
-rw-r--r--src/tpm2/crypto/openssl/CryptSmac.c156
-rw-r--r--src/tpm2/crypto/openssl/CryptSym.c771
-rw-r--r--src/tpm2/crypto/openssl/ExpDCache.c200
-rw-r--r--src/tpm2/crypto/openssl/ExpDCache_fp.h75
-rw-r--r--src/tpm2/crypto/openssl/Helpers.c625
-rw-r--r--src/tpm2/crypto/openssl/Helpers_fp.h117
-rw-r--r--src/tpm2/crypto/openssl/LibSupport.h98
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslDesSupport.c119
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h83
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslHash.h219
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslMath.c736
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslMath.h164
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslMath_fp.h152
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslSupport.c129
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h83
-rw-r--r--src/tpm2/crypto/openssl/TpmToOsslSym.h197
-rw-r--r--src/tpm2/crypto/openssl/consttime.txt76
-rw-r--r--src/tpm2/crypto/openssl/consttime.txt'58
54 files changed, 14822 insertions, 0 deletions
diff --git a/src/tpm2/crypto/CryptCmac_fp.h b/src/tpm2/crypto/CryptCmac_fp.h
new file mode 100644
index 0000000..f1df646
--- /dev/null
+++ b/src/tpm2/crypto/CryptCmac_fp.h
@@ -0,0 +1,86 @@
+/********************************************************************************/
+/* Message Authentication Codes Based on a Symmetric Block Cipher */
+/* Implementation of cryptographic functions for hashing. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptCmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2018 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTCMAC_FP_H
+#define CRYPTCMAC_FP_H
+#include "Tpm.h"
+
+UINT16
+CryptCmacStart(
+ SMAC_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParms,
+ TPM_ALG_ID macAlg,
+ TPM2B *key
+ );
+void
+CryptCmacData(
+ SMAC_STATES *state,
+ UINT32 size,
+ const BYTE *buffer
+ );
+UINT16
+CryptCmacEnd(
+ SMAC_STATES *state,
+ UINT32 outSize,
+ BYTE *outBuffer
+ );
+
+#endif
diff --git a/src/tpm2/crypto/CryptDes_fp.h b/src/tpm2/crypto/CryptDes_fp.h
new file mode 100644
index 0000000..1c1c3cd
--- /dev/null
+++ b/src/tpm2/crypto/CryptDes_fp.h
@@ -0,0 +1,82 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptDes_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTDES_FP_H
+#define CRYPTDES_FP_H
+
+UINT64
+CryptSetOddByteParity(
+ UINT64 k
+ );
+BOOL
+CryptDesValidateKey(
+ TPM2B_SYM_KEY *desKey // IN: key to validate
+ );
+TPM_RC
+CryptGenerateKeyDes(
+ TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
+ // for the new key.
+ TPMT_SENSITIVE *sensitive, // OUT: sensitive area
+ RAND_STATE *rand // IN: the "entropy" source for
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptEcc.h b/src/tpm2/crypto/CryptEcc.h
new file mode 100644
index 0000000..282e12f
--- /dev/null
+++ b/src/tpm2/crypto/CryptEcc.h
@@ -0,0 +1,103 @@
+/********************************************************************************/
+/* */
+/* Structure definitions used for ECC */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEcc.h 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+/* 10.1.2 CryptEcc.h */
+/* 10.1.2.1 Introduction */
+/* This file contains structure definitions used for ECC. The structures in this file are only used
+ internally. The ECC-related structures that cross the TPM interface are defined in TpmTypes.h */
+#ifndef _CRYPT_ECC_H
+#define _CRYPT_ECC_H
+
+/* 10.1.2.2 Structures */
+typedef struct ECC_CURVE
+{
+ const TPM_ECC_CURVE curveId;
+ const UINT16 keySizeBits;
+ const TPMT_KDF_SCHEME kdf;
+ const TPMT_ECC_SCHEME sign;
+ const ECC_CURVE_DATA *curveData; // the address of the curve data
+ const BYTE *OID;
+} ECC_CURVE;
+
+
+/* 10.1.2.2.1 Macros */
+/* This macro is used to instance an ECC_CURVE_DATA structure for the curve. This structure is
+ referenced by the ECC_CURVE structure */
+#define CURVE_DATA_DEF(CURVE) \
+ const ECC_CURVE_DATA CURVE = { \
+ (bigNum)&CURVE##_p_DATA, (bigNum)&CURVE##_n_DATA, (bigNum)&CURVE##_h_DATA, \
+ (bigNum)&CURVE##_a_DATA, (bigNum)&CURVE##_b_DATA, \
+ {(bigNum)&CURVE##_gX_DATA, (bigNum)&CURVE##_gY_DATA, (bigNum)&BN_ONE} };
+
+extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT];
+
+#define CURVE_DEF(CURVE) \
+ { \
+ TPM_ECC_##CURVE, \
+ CURVE##_KEY_SIZE, \
+ CURVE##_KDF, \
+ CURVE##_SIGN, \
+ &##CURVE, \
+ OID_ECC_##CURVE \
+ }
+#define CURVE_NAME(N)
+
+#endif
diff --git a/src/tpm2/crypto/CryptEccCrypt_fp.h b/src/tpm2/crypto/CryptEccCrypt_fp.h
new file mode 100644
index 0000000..3bb52ce
--- /dev/null
+++ b/src/tpm2/crypto/CryptEccCrypt_fp.h
@@ -0,0 +1,67 @@
+/********************************************************************************/
+/* */
+/* Include Headers for Internal Routines */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccCrypt_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* 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 (admin@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 CRYPTECCCRYPT_FP_H
+#define CRYPTECCCRYPT_FP_H
+
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptEccKeyExchange_fp.h b/src/tpm2/crypto/CryptEccKeyExchange_fp.h
new file mode 100644
index 0000000..e4f0b5a
--- /dev/null
+++ b/src/tpm2/crypto/CryptEccKeyExchange_fp.h
@@ -0,0 +1,78 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccKeyExchange_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTECCKEYEXCHANGE_FP_H
+#define CRYPTECCKEYEXCHANGE_FP_H
+
+LIB_EXPORT TPM_RC
+CryptEcc2PhaseKeyExchange(
+ TPMS_ECC_POINT *outZ1, // OUT: a computed point
+ TPMS_ECC_POINT *outZ2, // OUT: and optional second point
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM_ALG_ID scheme, // IN: the key exchange scheme
+ TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsB, // IN: static public party B key
+ TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptEccMain_fp.h b/src/tpm2/crypto/CryptEccMain_fp.h
new file mode 100644
index 0000000..2c04fc1
--- /dev/null
+++ b/src/tpm2/crypto/CryptEccMain_fp.h
@@ -0,0 +1,232 @@
+/********************************************************************************/
+/* */
+/* ECC Main */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccMain_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTECCMAIN_FP_H
+#define CRYPTECCMAIN_FP_H
+
+void
+EccSimulationEnd(
+ void
+ );
+BOOL
+CryptEccInit(
+ void
+ );
+BOOL
+CryptEccStartup(
+ void
+ );
+void
+ClearPoint2B(
+ TPMS_ECC_POINT *p // IN: the point
+ );
+LIB_EXPORT const ECC_CURVE *
+CryptEccGetParametersByCurveId(
+ TPM_ECC_CURVE curveId // IN: the curveID
+ );
+LIB_EXPORT UINT16
+CryptEccGetKeySizeForCurve(
+ TPM_ECC_CURVE curveId // IN: the curve
+ );
+const ECC_CURVE_DATA *
+GetCurveData(
+ TPM_ECC_CURVE curveId // IN: the curveID
+ );
+const BYTE *
+CryptEccGetOID(
+ TPM_ECC_CURVE curveId
+ );
+LIB_EXPORT TPM_ECC_CURVE
+CryptEccGetCurveByIndex(
+ UINT16 i
+ );
+LIB_EXPORT BOOL
+CryptEccGetParameter(
+ TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter
+ char p, // IN: the parameter selector
+ TPM_ECC_CURVE curveId // IN: the curve id
+ );
+TPMI_YES_NO
+CryptCapGetECCCurve(
+ TPM_ECC_CURVE curveID, // IN: the starting ECC curve
+ UINT32 maxCount, // IN: count of returned curves
+ TPML_ECC_CURVE *curveList // OUT: ECC curve list
+ );
+const TPMT_ECC_SCHEME *
+CryptGetCurveSignScheme(
+ TPM_ECC_CURVE curveId // IN: The curve selector
+ );
+BOOL
+CryptGenerateR(
+ TPM2B_ECC_PARAMETER *r, // OUT: the generated random value
+ UINT16 *c, // IN/OUT: count value.
+ TPMI_ECC_CURVE curveID, // IN: the curve for the value
+ TPM2B_NAME *name // IN: optional name of a key to
+ // associate with 'r'
+ );
+UINT16
+CryptCommit(
+ void
+ );
+void
+CryptEndCommit(
+ UINT16 c // IN: the counter value of the commitment
+ );
+BOOL
+CryptEccGetParameters(
+ TPM_ECC_CURVE curveId, // IN: ECC curve ID
+ TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters
+ );
+const bignum_t *
+BnGetCurvePrime(
+ TPM_ECC_CURVE curveId
+ );
+const bignum_t *
+BnGetCurveOrder(
+ TPM_ECC_CURVE curveId
+ );
+BOOL
+BnIsOnCurve(
+ pointConst Q,
+ const ECC_CURVE_DATA *C
+ );
+BOOL
+BnIsValidPrivateEcc(
+ bigConst x, // IN: private key to check
+ bigCurve E // IN: the curve to check
+ );
+LIB_EXPORT BOOL
+CryptEccIsValidPrivateKey(
+ TPM2B_ECC_PARAMETER *d,
+ TPM_ECC_CURVE curveId
+ );
+TPM_RC
+BnPointMult(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: optional point to multiply by 'd'
+ bigConst d, // IN: scalar for [d]S or [d]G
+ pointConst Q, // IN: optional second point
+ bigConst u, // IN: optional second scalar
+ bigCurve E // IN: curve parameters
+ );
+BOOL
+BnEccGetPrivate(
+ bigNum dOut, // OUT: the qualified random value
+ 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
+ );
+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
+ );
+LIB_EXPORT TPM_RC
+CryptEccNewKeyPair(
+ TPMS_ECC_POINT *Qout, // OUT: the public point
+ TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar
+ TPM_ECC_CURVE curveId // IN: the curve for the key
+ );
+LIB_EXPORT TPM_RC
+CryptEccPointMultiply(
+ TPMS_ECC_POINT *Rout, // OUT: the product point R
+ TPM_ECC_CURVE curveId, // IN: the curve to use
+ TPMS_ECC_POINT *Pin, // IN: first point (can be null)
+ TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin
+ // the Pin
+ TPMS_ECC_POINT *Qin, // IN: point Q
+ TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier
+ // of Q
+ );
+LIB_EXPORT BOOL
+CryptEccIsPointOnCurve(
+ TPM_ECC_CURVE curveId, // IN: the curve selector
+ TPMS_ECC_POINT *Qin // IN: the point.
+ );
+LIB_EXPORT TPM_RC
+CryptEccGenerateKey(
+ TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for
+ // the new key. The public key
+ // area will be replaced computed
+ // ECC public key
+ TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be
+ // updated to contain the private
+ // ECC key and the symmetric
+ // encryption key
+ RAND_STATE *rand // IN: if not NULL, the deterministic
+ // RNG state
+ );
+
+// libtpms added begin
+LIB_EXPORT BOOL
+CryptEccIsCurveRuntimeUsable(
+ TPMI_ECC_CURVE curveId
+ );
+// libtpms added end
+
+#endif
diff --git a/src/tpm2/crypto/CryptEccSignature_fp.h b/src/tpm2/crypto/CryptEccSignature_fp.h
new file mode 100644
index 0000000..5ee813e
--- /dev/null
+++ b/src/tpm2/crypto/CryptEccSignature_fp.h
@@ -0,0 +1,111 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccSignature_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTECCSIGNATURE_FP_H
+#define CRYPTECCSIGNATURE_FP_H
+
+TPM_RC
+BnSignEcdsa(
+ bigNum bnR, // OUT: r component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bigNum bnD, // IN: private signing key
+ const TPM2B_DIGEST *digest, // IN: the digest to sign
+ RAND_STATE *rand // IN: used in debug of signing
+ );
+LIB_EXPORT TPM_RC
+CryptEccSign(
+ TPMT_SIGNATURE *signature, // OUT: signature
+ OBJECT *signKey, // IN: ECC key to sign the hash
+ const TPM2B_DIGEST *digest, // IN: digest to sign
+ TPMT_ECC_SCHEME *scheme, // IN: signing scheme
+ RAND_STATE *rand
+ );
+TPM_RC
+BnValidateSignatureEcdsa(
+ bigNum bnR, // IN: r component of the signature
+ bigNum bnS, // IN: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bn_point_t *ecQ, // IN: the public point of the key
+ const TPM2B_DIGEST *digest // IN: the digest that was signed
+ );
+LIB_EXPORT TPM_RC
+CryptEccValidateSignature(
+ TPMT_SIGNATURE *signature, // IN: signature to be verified
+ OBJECT *signKey, // IN: ECC key signed the hash
+ const TPM2B_DIGEST *digest // IN: digest that was signed
+ );
+LIB_EXPORT TPM_RC
+CryptEccCommitCompute(
+ TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q
+ TPMS_ECC_POINT *L, // OUT: [r]B
+ TPMS_ECC_POINT *E, // OUT: [r]M
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPMS_ECC_POINT *M, // IN: M (optional)
+ TPMS_ECC_POINT *B, // IN: B (optional)
+ TPM2B_ECC_PARAMETER *d, // IN: d (optional)
+ TPM2B_ECC_PARAMETER *r // IN: the computed r value (required)
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptHash.h b/src/tpm2/crypto/CryptHash.h
new file mode 100644
index 0000000..20f52e8
--- /dev/null
+++ b/src/tpm2/crypto/CryptHash.h
@@ -0,0 +1,343 @@
+/********************************************************************************/
+/* */
+/* Hash structure definitions */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTHASH_H
+#define CRYPTHASH_H
+
+/* 10.1.3.1 Introduction */
+
+/* This header contains the hash structure definitions used in the TPM code to define the amount of
+ space to be reserved for the hash state. This allows the TPM code to not have to import all of
+ the symbols used by the hash computations. This lets the build environment of the TPM code not to
+ have include the header files associated with the CryptoEngine() code. */
+
+/* 10.1.3.2 Hash-related Structures */
+
+union SMAC_STATES;
+
+/* These definitions add the high-level methods for processing state that may be an SMAC */
+typedef void(* SMAC_DATA_METHOD)(
+ union SMAC_STATES *state,
+ UINT32 size,
+ const BYTE *buffer
+ );
+typedef UINT16(* SMAC_END_METHOD)(
+ union SMAC_STATES *state,
+ UINT32 size,
+ BYTE *buffer
+ );
+typedef struct sequenceMethods {
+ SMAC_DATA_METHOD data;
+ SMAC_END_METHOD end;
+} SMAC_METHODS;
+#define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start)
+
+/* These definitions are here because the SMAC state is in the union of hash states. */
+
+typedef struct tpmCmacState {
+ TPM_ALG_ID symAlg;
+ UINT16 keySizeBits;
+ INT16 bcount; // current count of bytes accumulated in IV
+ TPM2B_IV iv; // IV buffer
+ TPM2B_SYM_KEY symKey;
+} tpmCmacState_t;
+
+typedef union SMAC_STATES {
+#if ALG_CMAC
+ tpmCmacState_t cmac;
+#endif
+ UINT64 pad;
+} SMAC_STATES;
+
+typedef struct SMAC_STATE {
+ SMAC_METHODS smacMethods;
+ SMAC_STATES state;
+} SMAC_STATE;
+
+#if ALG_SHA1
+# define IF_IMPLEMENTED_SHA1(op) op(SHA1, Sha1)
+#else
+# define IF_IMPLEMENTED_SHA1(op)
+#endif
+#if ALG_SHA256
+# define IF_IMPLEMENTED_SHA256(op) op(SHA256, Sha256)
+#else
+# define IF_IMPLEMENTED_SHA256(op)
+#endif
+#if ALG_SHA384
+# define IF_IMPLEMENTED_SHA384(op) op(SHA384, Sha384)
+#else
+# define IF_IMPLEMENTED_SHA384(op)
+#endif
+#if ALG_SHA512
+# define IF_IMPLEMENTED_SHA512(op) op(SHA512, Sha512)
+#else
+# define IF_IMPLEMENTED_SHA512(op)
+#endif
+#if ALG_SM3_256
+# define IF_IMPLEMENTED_SM3_256(op) op(SM3_256, Sm3_256)
+#else
+# define IF_IMPLEMENTED_SM3_256(op)
+#endif
+#if ALG_SHA3_256
+# define IF_IMPLEMENTED_SHA3_256(op) op(SHA3_256, Sha3_256)
+#else
+# define IF_IMPLEMENTED_SHA3_256(op)
+#endif
+#if ALG_SHA3_384
+# define IF_IMPLEMENTED_SHA3_384(op) op(SHA3_384, Sha3_384)
+#else
+# define IF_IMPLEMENTED_SHA3_384(op)
+#endif
+#if ALG_SHA3_512
+# define IF_IMPLEMENTED_SHA3_512(op) op(SHA3_512, Sha3_512)
+#else
+# define IF_IMPLEMENTED_SHA3_512(op)
+#endif
+
+/* SHA512 added kgold */
+#define FOR_EACH_HASH(op) \
+ IF_IMPLEMENTED_SHA1(op) \
+ IF_IMPLEMENTED_SHA256(op) \
+ IF_IMPLEMENTED_SHA384(op) \
+ IF_IMPLEMENTED_SHA512(op) \
+ IF_IMPLEMENTED_SM3_256(op) \
+ IF_IMPLEMENTED_SHA3_256(op) \
+ IF_IMPLEMENTED_SHA3_384(op) \
+ IF_IMPLEMENTED_SHA3_512(op)
+
+#define HASH_TYPE(HASH, Hash) tpmHashState##HASH##_t Hash;
+
+typedef union
+{
+ FOR_EACH_HASH(HASH_TYPE)
+ // Additions for symmetric block cipher MAC
+#if SMAC_IMPLEMENTED
+ SMAC_STATE smac;
+#endif
+ // to force structure alignment to be no worse than HASH_ALIGNMENT
+#if HASH_ALIGNMENT == 8
+ uint64_t align;
+#else
+ uint32_t align;
+#endif
+} ANY_HASH_STATE;
+
+typedef ANY_HASH_STATE *PANY_HASH_STATE;
+typedef const ANY_HASH_STATE *PCANY_HASH_STATE;
+#define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b))
+/* MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that a hash state will
+ not be larger than twice the block size plus some overhead (in this case, 16 bytes). The overall
+ size needs to be as large as any of the hash contexts. The structure needs to start on an
+ alignment boundary and be an even multiple of the alignment */
+#define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16)
+#define MAX_HASH_STATE_SIZE_ALIGNED \
+ ALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT)
+/* This is an aligned byte array that will hold any of the hash contexts. */
+typedef ANY_HASH_STATE ALIGNED_HASH_STATE;
+/* The header associated with the hash library is expected to define the methods which include the
+ calling sequence. When not compiling CryptHash.c, the methods are not defined so we need
+ placeholder functions for the structures */
+#ifndef HASH_START_METHOD_DEF
+# define HASH_START_METHOD_DEF void (HASH_START_METHOD)(void)
+#endif
+#ifndef HASH_DATA_METHOD_DEF
+# define HASH_DATA_METHOD_DEF void (HASH_DATA_METHOD)(void)
+#endif
+#ifndef HASH_END_METHOD_DEF
+# define HASH_END_METHOD_DEF void (HASH_END_METHOD)(void)
+#endif
+#ifndef HASH_STATE_COPY_METHOD_DEF
+# define HASH_STATE_COPY_METHOD_DEF void (HASH_STATE_COPY_METHOD)(void)
+#endif
+#ifndef HASH_STATE_EXPORT_METHOD_DEF
+# define HASH_STATE_EXPORT_METHOD_DEF void (HASH_STATE_EXPORT_METHOD)(void)
+#endif
+#ifndef HASH_STATE_IMPORT_METHOD_DEF
+# define HASH_STATE_IMPORT_METHOD_DEF void (HASH_STATE_IMPORT_METHOD)(void)
+#endif
+/* Define the prototypical function call for each of the methods. This defines the order in which
+ the parameters are passed to the underlying function. */
+typedef HASH_START_METHOD_DEF;
+typedef HASH_DATA_METHOD_DEF;
+typedef HASH_END_METHOD_DEF;
+typedef HASH_STATE_COPY_METHOD_DEF;
+typedef HASH_STATE_EXPORT_METHOD_DEF;
+typedef HASH_STATE_IMPORT_METHOD_DEF;
+typedef struct _HASH_METHODS
+{
+ HASH_START_METHOD *start;
+ HASH_DATA_METHOD *data;
+ HASH_END_METHOD *end;
+ HASH_STATE_COPY_METHOD *copy; // Copy a hash block
+ HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash
+ // context
+ HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash
+ // context
+} HASH_METHODS, *PHASH_METHODS;
+
+#define HASH_TPM2B(HASH, Hash) TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE);
+
+FOR_EACH_HASH(HASH_TPM2B)
+
+/* When the TPM implements RSA, the hash-dependent OID pointers are part of the HASH_DEF. These
+ macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */
+#if ALG_RSA
+#define PKCS1_HASH_REF const BYTE *PKCS1;
+#define PKCS1_OID(NAME) , OID_PKCS1_##NAME
+#else
+#define PKCS1_HASH_REF
+#define PKCS1_OID(NAME)
+#endif
+
+/* When the TPM implements ECC, the hash-dependent OID pointers are part of the HASH_DEF. These
+ macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */
+#if ALG_ECDSA
+#define ECDSA_HASH_REF const BYTE *ECDSA;
+#define ECDSA_OID(NAME) , OID_ECDSA_##NAME
+#else
+#define ECDSA_HASH_REF
+#define ECDSA_OID(NAME)
+#endif
+
+typedef const struct
+{
+ HASH_METHODS method;
+ uint16_t blockSize;
+ uint16_t digestSize;
+ uint16_t contextSize;
+ uint16_t hashAlg;
+ const BYTE *OID;
+ PKCS1_HASH_REF // PKCS1 OID
+ ECDSA_HASH_REF // ECDSA OID
+} HASH_DEF, *PHASH_DEF;
+
+/* Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be:
+ HASH_DEF_TEMPLATE(Sha1, SHA1) This handles the difference in capitalization for the various
+ pieces. */
+
+#define HASH_DEF_TEMPLATE(HASH, Hash) \
+ HASH_DEF Hash##_Def= { \
+ {(HASH_START_METHOD *)&tpmHashStart_##HASH, \
+ (HASH_DATA_METHOD *)&tpmHashData_##HASH, \
+ (HASH_END_METHOD *)&tpmHashEnd_##HASH, \
+ (HASH_STATE_COPY_METHOD *)&tpmHashStateCopy_##HASH, \
+ (HASH_STATE_EXPORT_METHOD *)&tpmHashStateExport_##HASH, \
+ (HASH_STATE_IMPORT_METHOD *)&tpmHashStateImport_##HASH, \
+ }, \
+ HASH##_BLOCK_SIZE, /*block size */ \
+ HASH##_DIGEST_SIZE, /*data size */ \
+ sizeof(tpmHashState##HASH##_t), \
+ TPM_ALG_##HASH, OID_##HASH \
+ PKCS1_OID(HASH) ECDSA_OID(HASH)};
+
+/* These definitions are for the types that can be in a hash state structure. These types are used
+ in the cryptographic utilities. This is a define rather than an enum so that the size of this
+ field can be explicit. */
+typedef BYTE HASH_STATE_TYPE;
+#define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0)
+#define HASH_STATE_HASH ((HASH_STATE_TYPE) 1)
+#define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2)
+#if CC_MAC || CC_MAC_Start
+#define HASH_STATE_SMAC ((HASH_STATE_TYPE) 3)
+#endif
+/* This is the structure that is used for passing a context into the hashing functions. It should be
+ the same size as the function context used within the hashing functions. This is checked when the
+ hash function is initialized. This version uses a new layout for the contexts and a different
+ definition. The state buffer is an array of HASH_UNIT values so that a decent compiler will put
+ the structure on a HASH_UNIT boundary. If the structure is not properly aligned, the code that
+ manipulates the structure will copy to a properly aligned structure before it is used and copy
+ the result back. This just makes things slower. */
+/* NOTE: This version of the state had the pointer to the update method in the state. This is to
+ allow the SMAC functions to use the same structure without having to replicate the entire
+ HASH_DEF structure. */
+typedef struct _HASH_STATE
+{
+ HASH_STATE_TYPE type; // type of the context
+ TPM_ALG_ID hashAlg;
+ PHASH_DEF def;
+ ANY_HASH_STATE state;
+} HASH_STATE, *PHASH_STATE;
+typedef const HASH_STATE *PCHASH_STATE;
+
+/* 10.1.3.3 HMAC State Structures */
+/* This header contains the hash structure definitions used in the TPM code to define the amount of
+ space to be reserved for the hash state. This allows the TPM code to not have to import all of
+ the symbols used by the hash computations. This lets the build environment of the TPM code not to
+ have include the header files associated with the CryptoEngine() code. */
+
+/* An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure
+ when performing incremental HMAC operations. This structure contains a hash state and an HMAC key
+ and allows slightly better stack optimization than adding an HMAC key to each hash state. */
+typedef struct hmacState
+{
+ HASH_STATE hashState; // the hash state
+ TPM2B_HASH_BLOCK hmacKey; // the HMAC key
+} HMAC_STATE, *PHMAC_STATE;
+/* This is for the external hash state. This implementation assumes that the size of the exported
+ hash state is no larger than the internal hash state. */
+typedef struct
+{
+ BYTE buffer[sizeof(HASH_STATE)];
+} EXPORT_HASH_STATE, *PEXPORT_HASH_STATE;
+typedef const EXPORT_HASH_STATE *PCEXPORT_HASH_STATE;
+
+#endif // _CRYPT_HASH_H
diff --git a/src/tpm2/crypto/CryptHash_fp.h b/src/tpm2/crypto/CryptHash_fp.h
new file mode 100644
index 0000000..adf1ba9
--- /dev/null
+++ b/src/tpm2/crypto/CryptHash_fp.h
@@ -0,0 +1,219 @@
+/********************************************************************************/
+/* */
+/* Implementation of cryptographic functions for hashing. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptHash_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTHASH_FP_H
+#define CRYPTHASH_FP_H
+
+BOOL
+CryptHashInit(
+ void
+ );
+BOOL
+CryptHashStartup(
+ void
+ );
+PHASH_DEF
+CryptGetHashDef(
+ TPM_ALG_ID hashAlg
+ );
+BOOL
+CryptHashIsValidAlg(
+ TPM_ALG_ID hashAlg,
+ BOOL flag
+ );
+LIB_EXPORT TPM_ALG_ID
+CryptHashGetAlgByIndex(
+ UINT32 index // IN: the index
+ );
+LIB_EXPORT UINT16
+CryptHashGetDigestSize(
+ TPM_ALG_ID hashAlg // IN: hash algorithm to look up
+ );
+LIB_EXPORT UINT16
+CryptHashGetBlockSize(
+ TPM_ALG_ID hashAlg // IN: hash algorithm to look up
+ );
+LIB_EXPORT const BYTE *
+CryptHashGetOid(
+ TPM_ALG_ID hashAlg
+ );
+TPM_ALG_ID
+CryptHashGetContextAlg(
+ PHASH_STATE state // IN: the context to check
+ );
+LIB_EXPORT void
+CryptHashCopyState(
+ HASH_STATE *out, // OUT: destination of the state
+ const HASH_STATE *in // IN: source of the state
+ );
+void
+CryptHashExportState(
+ PCHASH_STATE internalFmt, // IN: the hash state formatted for use by
+ // library
+ PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state
+ );
+void
+CryptHashImportState(
+ PHASH_STATE internalFmt, // OUT: the hash state formatted for use by
+ // the library
+ PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state
+ );
+LIB_EXPORT UINT16
+CryptHashStart(
+ PHASH_STATE hashState, // OUT: the running hash state
+ TPM_ALG_ID hashAlg // IN: hash algorithm
+ );
+LIB_EXPORT void
+CryptDigestUpdate(
+ PHASH_STATE hashState, // IN: the hash context information
+ UINT32 dataSize, // IN: the size of data to be added
+ const BYTE *data // IN: data to be hashed
+ );
+LIB_EXPORT UINT16
+CryptHashEnd(
+ PHASH_STATE hashState, // IN: the state of hash stack
+ UINT32 dOutSize, // IN: size of digest buffer
+ BYTE *dOut // OUT: hash digest
+ );
+LIB_EXPORT UINT16
+CryptHashBlock(
+ TPM_ALG_ID hashAlg, // IN: The hash algorithm
+ UINT32 dataSize, // IN: size of buffer to hash
+ const BYTE *data, // IN: the buffer to hash
+ UINT32 dOutSize, // IN: size of the digest buffer
+ BYTE *dOut // OUT: digest buffer
+ );
+LIB_EXPORT void
+CryptDigestUpdate2B(
+ PHASH_STATE state, // IN: the digest state
+ const TPM2B *bIn // IN: 2B containing the data
+ );
+LIB_EXPORT UINT16
+CryptHashEnd2B(
+ PHASH_STATE state, // IN: the hash state
+ P2B digest // IN: the size of the buffer Out: requested
+ // number of bytes
+ );
+LIB_EXPORT void
+CryptDigestUpdateInt(
+ void *state, // IN: the state of hash stack
+ UINT32 intSize, // IN: the size of 'intValue' in bytes
+ UINT64 intValue // IN: integer value to be hashed
+ );
+LIB_EXPORT UINT16
+CryptHmacStart(
+ PHMAC_STATE state, // IN/OUT: the state buffer
+ TPM_ALG_ID hashAlg, // IN: the algorithm to use
+ UINT16 keySize, // IN: the size of the HMAC key
+ const BYTE *key // IN: the HMAC key
+ );
+LIB_EXPORT UINT16
+CryptHmacEnd(
+ PHMAC_STATE state, // IN: the hash state buffer
+ UINT32 dOutSize, // IN: size of digest buffer
+ BYTE *dOut // OUT: hash digest
+ );
+LIB_EXPORT UINT16
+CryptHmacStart2B(
+ PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used
+ // in HMAC update and completion
+ TPMI_ALG_HASH hashAlg, // IN: hash algorithm
+ P2B key // IN: HMAC key
+ );
+LIB_EXPORT UINT16
+CryptHmacEnd2B(
+ PHMAC_STATE hmacState, // IN: the state of HMAC stack
+ P2B digest // OUT: HMAC
+ );
+LIB_EXPORT UINT16
+CryptMGF_KDF(
+ UINT32 mSize, // IN: length of the mask to be produced
+ BYTE *mask, // OUT: buffer to receive the mask
+ TPM_ALG_ID hashAlg, // IN: hash to use
+ UINT32 seedSize, // IN: size of the seed
+ BYTE *seed, // IN: seed size
+ UINT32 counter // IN: counter initial value
+ );
+LIB_EXPORT UINT16
+CryptKDFa(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC
+ const TPM2B *key, // IN: HMAC key
+ const TPM2B *label, // IN: a label for the KDF
+ const TPM2B *contextU, // IN: context U
+ const TPM2B *contextV, // IN: context V
+ UINT32 sizeInBits, // IN: size of generated key in bits
+ BYTE *keyStream, // OUT: key buffer
+ UINT32 *counterInOut, // IN/OUT: caller may provide the iteration
+ UINT16 blocks // IN: If non-zero, this is the maximum number
+ );
+LIB_EXPORT UINT16
+CryptKDFe(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC
+ TPM2B *Z, // IN: Z
+ const TPM2B *label, // IN: a label value for the KDF
+ TPM2B *partyUInfo, // IN: PartyUInfo
+ TPM2B *partyVInfo, // IN: PartyVInfo
+ UINT32 sizeInBits, // IN: size of generated key in bits
+ BYTE *keyStream // OUT: key buffer
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptPrimeSieve_fp.h b/src/tpm2/crypto/CryptPrimeSieve_fp.h
new file mode 100644
index 0000000..66639a3
--- /dev/null
+++ b/src/tpm2/crypto/CryptPrimeSieve_fp.h
@@ -0,0 +1,101 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptPrimeSieve_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTPRIMESIEVE_FP_H
+#define CRYPTPRIMESIEVE_FP_H
+
+LIB_EXPORT void
+RsaAdjustPrimeLimit(
+ uint32_t requestedPrimes
+ );
+LIB_EXPORT uint32_t
+RsaNextPrime(
+ uint32_t lastPrime
+ );
+LIB_EXPORT int
+FindNthSetBit(
+ const UINT16 aSize, // IN: the size of the array to check
+ const BYTE *a, // IN: the array to check
+ const UINT32 n // IN, the number of the SET bit
+ );
+LIB_EXPORT UINT32
+PrimeSieve(
+ bigNum bnN, // IN/OUT: number to sieve
+ UINT32 fieldSize, // IN: size of the field area in bytes
+ BYTE *field // IN: field
+ );
+LIB_EXPORT uint32_t
+SetFieldSize(
+ uint32_t newFieldSize
+ );
+LIB_EXPORT TPM_RC
+PrimeSelectWithSieve(
+ bigNum candidate, // IN/OUT: The candidate to filter
+ UINT32 e, // IN: the exponent
+ RAND_STATE *rand // IN: the random number generator state
+ );
+void
+RsaSimulationEnd(
+ void
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptPrime_fp.h b/src/tpm2/crypto/CryptPrime_fp.h
new file mode 100644
index 0000000..d9acfcb
--- /dev/null
+++ b/src/tpm2/crypto/CryptPrime_fp.h
@@ -0,0 +1,104 @@
+/********************************************************************************/
+/* */
+/* Code for prime validation */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptPrime_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTPRIME_FP_H
+#define CRYPTPRIME_FP_H
+
+BOOL
+IsPrimeInt(
+ uint32_t n
+ );
+BOOL
+BnIsProbablyPrime(
+ bigNum prime, // IN:
+ RAND_STATE *rand // IN: the random state just
+ // in case Miller-Rabin is required
+ );
+UINT32
+MillerRabinRounds(
+ UINT32 bits // IN: Number of bits in the RSA prime
+ );
+BOOL
+MillerRabin(
+ bigNum bnW,
+ RAND_STATE *rand
+ );
+TPM_RC
+RsaCheckPrime(
+ bigNum prime,
+ UINT32 exponent,
+ RAND_STATE *rand
+ );
+LIB_EXPORT void
+RsaAdjustPrimeCandidate(
+ bigNum prime,
+ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added
+ );
+TPM_RC
+BnGeneratePrimeForRSA(
+ bigNum prime,
+ UINT32 bits,
+ UINT32 exponent,
+ RAND_STATE *rand
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptRand.h b/src/tpm2/crypto/CryptRand.h
new file mode 100644
index 0000000..d339285
--- /dev/null
+++ b/src/tpm2/crypto/CryptRand.h
@@ -0,0 +1,193 @@
+/********************************************************************************/
+/* */
+/* DRBG with a behavior according to SP800-90A */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRand.h 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+/* 10.1.4 CryptRand.h */
+/* 10.1.4.1 Introduction */
+/* This file contains constant definition shared by CryptUtil() and the parts of the Crypto
+ Engine. */
+#ifndef _CRYPT_RAND_H
+#define _CRYPT_RAND_H
+/* DRBG Structures and Defines Values and structures for the random number generator. These values
+ are defined in this header file so that the size of the RNG state can be known to TPM.lib. This
+ allows the allocation of some space in NV memory for the state to be stored on an orderly
+ shutdown. The DRBG based on a symmetric block cipher is defined by three values, */
+/* a) the key size */
+/* b) the block size (the IV size) */
+/* c) the symmetric algorithm */
+#define DRBG_KEY_SIZE_BITS AES_MAX_KEY_SIZE_BITS
+#define DRBG_IV_SIZE_BITS (AES_MAX_BLOCK_SIZE * 8)
+#define DRBG_ALGORITHM TPM_ALG_AES
+typedef tpmKeyScheduleAES DRBG_KEY_SCHEDULE;
+#define DRBG_ENCRYPT_SETUP(key, keySizeInBits, schedule) \
+ TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule)
+#define DRBG_ENCRYPT(keySchedule, in, out) \
+ TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out))
+#if ((DRBG_KEY_SIZE_BITS % RADIX_BITS) != 0) \
+ || ((DRBG_IV_SIZE_BITS % RADIX_BITS) != 0)
+#error "Key size and IV for DRBG must be even multiples of the radix"
+#endif
+#if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0
+#error "Key size for DRBG must be even multiple of the cypher block size"
+#endif
+/* Derived values */
+#define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48)
+#define DRBG_MAX_REQEST_SIZE (1 << 32)
+#define pDRBG_KEY(seed) ((DRBG_KEY *)&(((BYTE *)(seed))[0]))
+#define pDRBG_IV(seed) ((DRBG_IV *)&(((BYTE *)(seed))[DRBG_KEY_SIZE_BYTES]))
+#define DRBG_KEY_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS))
+#define DRBG_KEY_SIZE_BYTES (DRBG_KEY_SIZE_WORDS * RADIX_BYTES)
+#define DRBG_IV_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS))
+#define DRBG_IV_SIZE_BYTES (DRBG_IV_SIZE_WORDS * RADIX_BYTES)
+#define DRBG_SEED_SIZE_WORDS (DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS)
+#define DRBG_SEED_SIZE_BYTES (DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES)
+typedef union
+{
+ BYTE bytes[DRBG_KEY_SIZE_BYTES];
+ crypt_uword_t words[DRBG_KEY_SIZE_WORDS];
+} DRBG_KEY;
+typedef union
+{
+ BYTE bytes[DRBG_IV_SIZE_BYTES];
+ crypt_uword_t words[DRBG_IV_SIZE_WORDS];
+} DRBG_IV;
+typedef union
+{
+ BYTE bytes[DRBG_SEED_SIZE_BYTES];
+ crypt_uword_t words[DRBG_SEED_SIZE_WORDS];
+} DRBG_SEED;
+#define CTR_DRBG_MAX_REQUESTS_PER_RESEED ((UINT64)1 << 20)
+#define CTR_DRBG_MAX_BYTES_PER_REQUEST (1 << 16)
+# define CTR_DRBG_MIN_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES
+# define CTR_DRBG_MAX_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES
+# define CTR_DRBG_MAX_ADDITIONAL_INPUT_LENGTH DRBG_SEED_SIZE_BYTES
+#define TESTING (1 << 0)
+#define ENTROPY (1 << 1)
+#define TESTED (1 << 2)
+#define IsTestStateSet(BIT) ((g_cryptoSelfTestState.rng & BIT) != 0)
+#define SetTestStateBit(BIT) (g_cryptoSelfTestState.rng |= BIT)
+#define ClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT)
+#define IsSelfTest() IsTestStateSet(TESTING)
+#define SetSelfTest() SetTestStateBit(TESTING)
+#define ClearSelfTest() ClearTestStateBit(TESTING)
+#define IsEntropyBad() IsTestStateSet(ENTROPY)
+#define SetEntropyBad() SetTestStateBit(ENTROPY)
+#define ClearEntropyBad() ClearTestStateBit(ENTROPY)
+#define IsDrbgTested() IsTestStateSet(TESTED)
+#define SetDrbgTested() SetTestStateBit(TESTED)
+#define ClearDrbgTested() ClearTestStateBit(TESTED)
+ typedef struct
+ {
+ UINT64 reseedCounter;
+ UINT32 magic;
+ DRBG_SEED seed; // contains the key and IV for the counter mode DRBG
+ SEED_COMPAT_LEVEL seedCompatLevel; // libtpms added: the compatibility level for keeping backwards compatibility
+ UINT32 lastValue[4]; // used when the TPM does continuous self-test
+ // for FIPS compliance of DRBG
+ } DRBG_STATE, *pDRBG_STATE;
+#define DRBG_MAGIC ((UINT32) 0x47425244) // "DRBG" backwards so that it displays
+typedef struct KDF_STATE
+{
+ UINT64 counter;
+ UINT32 magic;
+ UINT32 limit;
+ TPM2B *seed;
+ const TPM2B *label;
+ TPM2B *context;
+ TPM_ALG_ID hash;
+ TPM_ALG_ID kdf;
+ UINT16 digestSize;
+ TPM2B_DIGEST residual;
+} KDF_STATE, *pKDR_STATE;
+#define KDF_MAGIC ((UINT32) 0x4048444a) // "KDF " backwards
+/* Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit
+ magic number */
+typedef union
+{
+ DRBG_STATE drbg;
+ KDF_STATE kdf;
+} RAND_STATE;
+/* This is the state used when the library uses a random number generator. A special function is
+ installed for the library to call. That function picks up the state from this location and uses
+ it for the generation of the random number. */
+extern RAND_STATE *s_random;
+/* When instrumenting RSA key sieve */
+#if RSA_INSTRUMENT
+#define PRIME_INDEX(x) ((x) == 512 ? 0 : (x) == 1024 ? 1 : 2)
+# define INSTRUMENT_SET(a, b) ((a) = (b))
+# define INSTRUMENT_ADD(a, b) (a) = (a) + (b)
+# define INSTRUMENT_INC(a) (a) = (a) + 1
+extern UINT32 PrimeIndex;
+extern UINT32 failedAtIteration[10];
+extern UINT32 PrimeCounts[3];
+extern UINT32 MillerRabinTrials[3];
+extern UINT32 totalFieldsSieved[3];
+extern UINT32 bitsInFieldAfterSieve[3];
+extern UINT32 emptyFieldsSieved[3];
+extern UINT32 noPrimeFields[3];
+extern UINT32 primesChecked[3];
+extern UINT16 lastSievePrime;
+#else
+# define INSTRUMENT_SET(a, b)
+# define INSTRUMENT_ADD(a, b)
+# define INSTRUMENT_INC(a)
+#endif
+#endif // _CRYPT_RAND_H
+
diff --git a/src/tpm2/crypto/CryptRand_fp.h b/src/tpm2/crypto/CryptRand_fp.h
new file mode 100644
index 0000000..e5dee5b
--- /dev/null
+++ b/src/tpm2/crypto/CryptRand_fp.h
@@ -0,0 +1,158 @@
+/********************************************************************************/
+/* */
+/* DRBG with a behavior according to SP800-90A */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRand_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTRAND_FP_H
+#define CRYPTRAND_FP_H
+
+BOOL
+DRBG_GetEntropy(
+ UINT32 requiredEntropy, // IN: requested number of bytes of full
+ // entropy
+ BYTE *entropy // OUT: buffer to return collected entropy
+ );
+void
+IncrementIv(
+ DRBG_IV *iv
+ );
+BOOL
+DRBG_Reseed(
+ DRBG_STATE *drbgState, // IN: the state to update
+ DRBG_SEED *providedEntropy, // IN: entropy
+ DRBG_SEED *additionalData // IN:
+ );
+BOOL
+DRBG_SelfTest(
+ void
+ );
+LIB_EXPORT TPM_RC
+CryptRandomStir(
+ UINT16 additionalDataSize,
+ BYTE *additionalData
+ );
+LIB_EXPORT UINT16
+CryptRandomGenerate(
+ UINT16 randomSize,
+ BYTE *buffer
+ );
+LIB_EXPORT BOOL
+DRBG_InstantiateSeededKdf(
+ KDF_STATE *state, // IN: buffer to hold the state
+ TPM_ALG_ID hashAlg, // IN: hash algorithm
+ TPM_ALG_ID kdf, // IN: the KDF to use
+ TPM2B *seed, // IN: the seed to use
+ const TPM2B *label, // IN: a label for the generation process.
+ TPM2B *context, // IN: the context value
+ UINT32 limit // IN: Maximum number of bits from the KDF
+ );
+LIB_EXPORT void
+DRBG_AdditionalData(
+ DRBG_STATE *drbgState, // IN:OUT state to update
+ TPM2B *additionalData // IN: value to incorporate
+ );
+LIB_EXPORT TPM_RC
+DRBG_InstantiateSeeded(
+ DRBG_STATE *drbgState, // IN: buffer to hold the state
+ const TPM2B *seed, // IN: the seed to use
+ const TPM2B *purpose, // IN: a label for the generation process.
+ const TPM2B *name, // IN: name of the object
+ const TPM2B *additional, // IN: additional data
+ SEED_COMPAT_LEVEL seedCompatLevel// IN: compatibility level (associated with seed); libtpms added
+ );
+LIB_EXPORT BOOL
+CryptRandStartup(
+ void
+ );
+LIB_EXPORT BOOL
+CryptRandInit(
+ void
+ );
+LIB_EXPORT UINT16
+DRBG_Generate(
+ RAND_STATE *state,
+ BYTE *random, // OUT: buffer to receive the random values
+ UINT16 randomSize // IN: the number of bytes to generate
+ );
+// libtpms added begin
+LIB_EXPORT SEED_COMPAT_LEVEL
+DRBG_GetSeedCompatLevel(
+ RAND_STATE *state // IN
+ );
+// libtpms added end
+LIB_EXPORT BOOL
+DRBG_Instantiate(
+ DRBG_STATE *drbgState, // OUT: the instantiated value
+ UINT16 pSize, // IN: Size of personalization string
+ BYTE *personalization // IN: The personalization string
+ );
+LIB_EXPORT TPM_RC
+DRBG_Uninstantiate(
+ DRBG_STATE *drbgState // IN/OUT: working state to erase
+ );
+LIB_EXPORT NUMBYTES
+CryptRandMinMax(
+ BYTE *out,
+ UINT32 max,
+ UINT32 min,
+ RAND_STATE *rand
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptRsa.h b/src/tpm2/crypto/CryptRsa.h
new file mode 100644
index 0000000..f3c1fa1
--- /dev/null
+++ b/src/tpm2/crypto/CryptRsa.h
@@ -0,0 +1,99 @@
+/********************************************************************************/
+/* */
+/* RSA-related structures and defines */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRsa.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+// 10.1.5 CryptRsa.h
+// This file contains the RSA-related structures and defines.
+#ifndef _CRYPT_RSA_H
+#define _CRYPT_RSA_H
+
+/* This structure is a succinct representation of the cryptographic components of an RSA key. It is
+ used in testing */
+typedef struct
+{
+ UINT32 exponent; // The public exponent pointer
+ TPM2B *publicKey; // Pointer to the public modulus
+ TPM2B *privateKey; // The private prime
+} RSA_KEY;
+/* These values are used in the bigNum representation of various RSA values. */
+#define RSA_BITS (MAX_RSA_KEY_BYTES * 8)
+BN_TYPE(rsa, RSA_BITS);
+#define BN_RSA(name) BN_VAR(name, RSA_BITS)
+#define BN_RSA_INITIALIZED(name, initializer) \
+ BN_INITIALIZED(name, RSA_BITS, initializer)
+#define BN_PRIME(name) BN_VAR(name, (RSA_BITS / 2))
+BN_TYPE(prime, (RSA_BITS / 2));
+#define BN_PRIME_INITIALIZED(name, initializer) \
+ BN_INITIALIZED(name, RSA_BITS / 2, initializer)
+typedef struct privateExponent
+{
+#if CRT_FORMAT_RSA == NO
+ bn_rsa_t D;
+#else
+ bn_prime_t Q;
+ bn_prime_t dP;
+ bn_prime_t dQ;
+ bn_prime_t qInv;
+#endif // CRT_FORMAT_RSA
+} privateExponent_t;
+#endif // _CRYPT_RSA_H
+
+
+
diff --git a/src/tpm2/crypto/CryptRsa_fp.h b/src/tpm2/crypto/CryptRsa_fp.h
new file mode 100644
index 0000000..d473b51
--- /dev/null
+++ b/src/tpm2/crypto/CryptRsa_fp.h
@@ -0,0 +1,139 @@
+/********************************************************************************/
+/* */
+/* Implementation of cryptographic primitives for RSA */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRsa_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTRSA_FP_H
+#define CRYPTRSA_FP_H
+
+BOOL
+CryptRsaInit(
+ void
+ );
+BOOL
+CryptRsaStartup(
+ void
+ );
+void
+RsaInitializeExponent(
+ privateExponent_t *pExp
+ );
+INT16
+CryptRsaPssSaltSize(
+ INT16 hashSize,
+ INT16 outSize
+ );
+TPMT_RSA_DECRYPT*
+CryptRsaSelectScheme(
+ TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key
+ TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme
+ );
+TPM_RC
+CryptRsaLoadPrivateExponent(
+ OBJECT *rsaKey // IN: the RSA key object
+ );
+LIB_EXPORT TPM_RC
+CryptRsaEncrypt(
+ TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data
+ TPM2B *dIn, // IN: the data to encrypt
+ OBJECT *key, // IN: the key used for encryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash
+ // if needed
+ const TPM2B *label, // IN: in case it is needed
+ RAND_STATE *rand // IN: random number generator
+ // state (mostly for testing)
+ );
+LIB_EXPORT TPM_RC
+CryptRsaDecrypt(
+ TPM2B *dOut, // OUT: the decrypted data
+ TPM2B *cIn, // IN: the data to decrypt
+ OBJECT *key, // IN: the key to use for decryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme
+ const TPM2B *label // IN: in case it is needed for the scheme
+ );
+LIB_EXPORT TPM_RC
+CryptRsaSign(
+ TPMT_SIGNATURE *sigOut,
+ OBJECT *key, // IN: key to use
+ TPM2B_DIGEST *hIn, // IN: the digest to sign
+ RAND_STATE *rand // IN: the random number generator
+ // to use (mostly for testing)
+ );
+LIB_EXPORT TPM_RC
+CryptRsaValidateSignature(
+ TPMT_SIGNATURE *sig, // IN: signature
+ OBJECT *key, // IN: public modulus
+ TPM2B_DIGEST *digest // IN: The digest being validated
+ );
+LIB_EXPORT TPM_RC
+CryptRsaGenerateKey(
+ OBJECT *rsaKey, // IN/OUT: The object structure in which
+ // the key is created.
+ RAND_STATE *rand // IN: if not NULL, the deterministic
+ // RNG state
+ );
+INT16
+MakeDerTag(
+ TPM_ALG_ID hashAlg,
+ INT16 sizeOfBuffer,
+ BYTE *buffer
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptSelfTest_fp.h b/src/tpm2/crypto/CryptSelfTest_fp.h
new file mode 100644
index 0000000..8dd3822
--- /dev/null
+++ b/src/tpm2/crypto/CryptSelfTest_fp.h
@@ -0,0 +1,87 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSelfTest_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTSELFTEST_FP_H
+#define CRYPTSELFTEST_FP_H
+
+LIB_EXPORT
+TPM_RC
+CryptSelfTest(
+ TPMI_YES_NO fullTest // IN: if full test is required
+ );
+TPM_RC
+CryptIncrementalSelfTest(
+ TPML_ALG *toTest, // IN: list of algorithms to be tested
+ TPML_ALG *toDoList // OUT: list of algorithms needing test
+ );
+void
+CryptInitializeToTest(
+ void
+ );
+LIB_EXPORT
+TPM_RC
+CryptTestAlgorithm(
+ TPM_ALG_ID alg,
+ ALGORITHM_VECTOR *toTest
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptSmac_fp.h b/src/tpm2/crypto/CryptSmac_fp.h
new file mode 100644
index 0000000..b93e8ac
--- /dev/null
+++ b/src/tpm2/crypto/CryptSmac_fp.h
@@ -0,0 +1,98 @@
+/********************************************************************************/
+/* Message Authentication Codes Based on a Symmetric Block Cipher */
+/* Implementation of cryptographic functions for hashing. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2018 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTSMAC_FP_H
+#define CRYPTSMAC_FP_H
+#include "Tpm.h"
+
+UINT16
+CryptSmacStart(
+ HASH_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParameters,
+ TPM_ALG_ID macAlg,
+ TPM2B *key
+ );
+UINT16
+CryptMacStart(
+ HMAC_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParameters,
+ TPM_ALG_ID macAlg,
+ TPM2B *key
+ );
+UINT16
+CryptMacEnd(
+ HMAC_STATE *state,
+ UINT32 size,
+ BYTE *buffer
+ );
+UINT16
+CryptMacEnd(
+ HMAC_STATE *state,
+ UINT32 size,
+ BYTE *buffer
+ );
+UINT16
+CryptMacEnd2B (
+ HMAC_STATE *state,
+ TPM2B *data
+ );
+
+#endif
diff --git a/src/tpm2/crypto/CryptSym.h b/src/tpm2/crypto/CryptSym.h
new file mode 100644
index 0000000..66cfb97
--- /dev/null
+++ b/src/tpm2/crypto/CryptSym.h
@@ -0,0 +1,142 @@
+/********************************************************************************/
+/* */
+/* Implementation of the symmetric block cipher modes */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSym.h 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2017 - 2021 */
+/* */
+/********************************************************************************/
+
+
+#ifndef CRYPTSYM_H
+#define CRYPTSYM_H
+
+#if ALG_AES
+# define IF_IMPLEMENTED_AES(op) op(AES, aes)
+#else
+# define IF_IMPLEMENTED_AES(op)
+#endif
+#if ALG_SM4
+# define IF_IMPLEMENTED_SM4(op) op(SM4, sm4)
+#else
+# define IF_IMPLEMENTED_SM4(op)
+#endif
+#if ALG_CAMELLIA
+# define IF_IMPLEMENTED_CAMELLIA(op) op(CAMELLIA, camellia)
+#else
+# define IF_IMPLEMENTED_CAMELLIA(op)
+#endif
+#if ALG_TDES
+# define IF_IMPLEMENTED_TDES(op) op(TDES, tdes)
+#else
+# define IF_IMPLEMENTED_TDES(op)
+#endif
+
+#define FOR_EACH_SYM(op) \
+ IF_IMPLEMENTED_AES(op) \
+ IF_IMPLEMENTED_SM4(op) \
+ IF_IMPLEMENTED_CAMELLIA(op) \
+ IF_IMPLEMENTED_TDES(op)
+
+ /* libtpms added begin */
+#define FOR_EACH_SYM_WITHOUT_TDES(op) \
+ IF_IMPLEMENTED_AES(op) \
+ IF_IMPLEMENTED_SM4(op) \
+ IF_IMPLEMENTED_CAMELLIA(op) /* libtpms added end */
+
+/* Macros for creating the key schedule union */
+
+#define KEY_SCHEDULE(SYM, sym) tpmKeySchedule##SYM sym;
+//#define TDES DES[3] /* libtpms commented */
+typedef union tpmCryptKeySchedule_t {
+ FOR_EACH_SYM_WITHOUT_TDES(KEY_SCHEDULE) /* libtpms changed from FOR_EACH_SYM */
+ tpmKeyScheduleTDES tdes[3]; /* libtpms added */
+
+#if SYMMETRIC_ALIGNMENT == 8
+ uint64_t alignment;
+#else
+ uint32_t alignment;
+#endif
+} tpmCryptKeySchedule_t;
+
+/* Each block cipher within a library is expected to conform to the same calling conventions with
+ three parameters (keySchedule, in, and out) in the same order. That means that all algorithms
+ would use the same order of the same parameters. The code is written assuming the (keySchedule,
+ in, and out) order. However, if the library uses a different order, the order can be changed with
+ a SWIZZLE macro that puts the parameters in the correct order. Note that all algorithms have to
+ use the same order and number of parameters because the code to build the calling list is common
+ for each call to encrypt or decrypt with the algorithm chosen by setting a function pointer to
+ select the algorithm that is used. */
+# define ENCRYPT(keySchedule, in, out) \
+ encrypt(SWIZZLE(keySchedule, in, out))
+# define DECRYPT(keySchedule, in, out) \
+ decrypt(SWIZZLE(keySchedule, in, out))
+
+/* Note that the macros rely on encrypt as local values in the functions that use these
+ macros. Those parameters are set by the macro that set the key schedule to be used for the
+ call. */
+
+#define ENCRYPT_CASE(ALG, alg) \
+ case TPM_ALG_##ALG: \
+ TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \
+ encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \
+ break;
+#define DECRYPT_CASE(ALG, alg) \
+ case TPM_ALG_##ALG: \
+ TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \
+ decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \
+ break;
+
+#endif
diff --git a/src/tpm2/crypto/CryptSym_fp.h b/src/tpm2/crypto/CryptSym_fp.h
new file mode 100644
index 0000000..e78215f
--- /dev/null
+++ b/src/tpm2/crypto/CryptSym_fp.h
@@ -0,0 +1,111 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSym_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTSYM_FP_H
+#define CRYPTSYM_FP_H
+
+BOOL
+CryptSymInit(
+ void
+ );
+BOOL
+CryptSymStartup(
+ void
+ );
+LIB_EXPORT INT16
+CryptGetSymmetricBlockSize(
+ TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm
+ UINT16 keySizeInBits // IN: the key size
+ );
+LIB_EXPORT TPM_RC
+CryptSymmetricEncrypt(
+ BYTE *dOut, // OUT:
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ );
+LIB_EXPORT TPM_RC
+CryptSymmetricDecrypt(
+ BYTE *dOut, // OUT: decrypted data
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ );
+TPM_RC
+CryptSymKeyValidate(
+ TPMT_SYM_DEF_OBJECT *symDef,
+ TPM2B_SYM_KEY *key
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/CryptTest.h b/src/tpm2/crypto/CryptTest.h
new file mode 100644
index 0000000..ce2321b
--- /dev/null
+++ b/src/tpm2/crypto/CryptTest.h
@@ -0,0 +1,93 @@
+/********************************************************************************/
+/* */
+/* constant definitions used for self-test. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptTest.h 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTTEST_H
+#define CRYPTTEST_H
+
+/* 10.1.7 CryptTest.h */
+/* This file contains constant definitions used for self test */
+/* This is the definition of a bit array with one bit per algorithm */
+/* NOTE: Since bit numbering starts at zero, when TPM_ALG_LAST is a multiple of 8,
+ ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, for example,
+ when TPM_ALG_LAST is 8, ALGORITHM_VECTOR will need 2 bytes. */
+#define ALGORITHM_VECTOR_BYTES ((TPM_ALG_LAST + 8) / 8)
+typedef BYTE ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES];
+#ifdef TEST_SELF_TEST
+LIB_EXPORT extern ALGORITHM_VECTOR LibToTest;
+#endif
+/* This structure is used to contain self-test tracking information for the cryptographic
+ modules. Each of the major modules is given a 32-bit value in which it may maintain its own self
+ test information. The convention for this state is that when all of the bits in this structure
+ are 0, all functions need to be tested. */
+typedef struct
+{
+ UINT32 rng;
+ UINT32 hash;
+ UINT32 sym;
+#if ALG_RSA
+ UINT32 rsa;
+#endif
+#if ALG_ECC
+ UINT32 ecc;
+#endif
+} CRYPTO_SELF_TEST_STATE;
+#endif // _CRYPT_TEST_H
+
diff --git a/src/tpm2/crypto/CryptUtil_fp.h b/src/tpm2/crypto/CryptUtil_fp.h
new file mode 100644
index 0000000..2ca16e7
--- /dev/null
+++ b/src/tpm2/crypto/CryptUtil_fp.h
@@ -0,0 +1,232 @@
+/********************************************************************************/
+/* */
+/* Interfaces to the CryptoEngine */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptUtil_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef CRYPTUTIL_FP_H
+#define CRYPTUTIL_FP_H
+
+BOOL
+CryptIsSchemeAnonymous(
+ TPM_ALG_ID scheme // IN: the scheme algorithm to test
+ );
+void
+ParmDecryptSym(
+ TPM_ALG_ID symAlg, // IN: the symmetric algorithm
+ TPM_ALG_ID hash, // IN: hash algorithm for KDFa
+ UINT16 keySizeInBits, // IN: the key size in bits
+ TPM2B *key, // IN: KDF HMAC key
+ TPM2B *nonceCaller, // IN: nonce caller
+ TPM2B *nonceTpm, // IN: nonce TPM
+ UINT32 dataSize, // IN: size of parameter buffer
+ BYTE *data // OUT: buffer to be decrypted
+ );
+void
+ParmEncryptSym(
+ TPM_ALG_ID symAlg, // IN: symmetric algorithm
+ TPM_ALG_ID hash, // IN: hash algorithm for KDFa
+ UINT16 keySizeInBits, // IN: AES key size in bits
+ TPM2B *key, // IN: KDF HMAC key
+ TPM2B *nonceCaller, // IN: nonce caller
+ TPM2B *nonceTpm, // IN: nonce TPM
+ UINT32 dataSize, // IN: size of parameter buffer
+ BYTE *data // OUT: buffer to be encrypted
+ );
+void
+CryptXORObfuscation(
+ TPM_ALG_ID hash, // IN: hash algorithm for KDF
+ TPM2B *key, // IN: KDF key
+ TPM2B *contextU, // IN: contextU
+ TPM2B *contextV, // IN: contextV
+ UINT32 dataSize, // IN: size of data buffer
+ BYTE *data // IN/OUT: data to be XORed in place
+ );
+BOOL
+CryptInit(
+ void
+ );
+BOOL
+CryptStartup(
+ STARTUP_TYPE type // IN: the startup type
+ );
+BOOL
+CryptIsAsymAlgorithm(
+ TPM_ALG_ID algID // IN: algorithm ID
+ );
+TPM_RC
+CryptSecretEncrypt(
+ OBJECT *encryptKey, // IN: encryption key object
+ const TPM2B *label, // IN: a null-terminated string as L
+ TPM2B_DATA *data, // OUT: secret value
+ TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure
+ );
+TPM_RC
+CryptSecretDecrypt(
+ OBJECT *decryptKey, // IN: decrypt key
+ TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for
+ // symmetric decryption. For
+ // asymmetric decryption, this
+ // parameter is NULL
+ const TPM2B *label, // IN: a value for L
+ TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret
+ TPM2B_DATA *data // OUT: decrypted secret value
+ );
+void
+CryptParameterEncryption(
+ TPM_HANDLE handle, // IN: encrypt session handle
+ TPM2B *nonceCaller, // IN: nonce caller
+ UINT16 leadingSizeInByte, // IN: the size of the leading size field in
+ // bytes
+ TPM2B_AUTH *extraKey, // IN: additional key material other than
+ // sessionAuth
+ BYTE *buffer // IN/OUT: parameter buffer to be encrypted
+ );
+TPM_RC
+CryptParameterDecryption(
+ TPM_HANDLE handle, // IN: encrypted session handle
+ TPM2B *nonceCaller, // IN: nonce caller
+ UINT32 bufferSize, // IN: size of parameter buffer
+ UINT16 leadingSizeInByte, // IN: the size of the leading size field in
+ // byte
+ TPM2B_AUTH *extraKey, // IN: the authValue
+ BYTE *buffer // IN/OUT: parameter buffer to be decrypted
+ );
+void
+CryptComputeSymmetricUnique(
+ TPMT_PUBLIC *publicArea, // IN: the object's public area
+ TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area
+ TPM2B_DIGEST *unique // OUT: unique buffer
+ );
+TPM_RC
+CryptCreateObject(
+ OBJECT *object, // IN: new object structure pointer
+ TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation
+ RAND_STATE *rand // IN: the random number generator
+ // to use
+ );
+TPMI_ALG_HASH
+CryptGetSignHashAlg(
+ TPMT_SIGNATURE *auth // IN: signature
+ );
+BOOL
+CryptIsSplitSign(
+ TPM_ALG_ID scheme // IN: the algorithm selector
+ );
+BOOL
+CryptIsAsymSignScheme(
+ TPMI_ALG_PUBLIC publicType, // IN: Type of the object
+ TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme
+ );
+BOOL
+CryptIsAsymDecryptScheme(
+ TPMI_ALG_PUBLIC publicType, // IN: Type of the object
+ TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme
+ );
+BOOL
+CryptSelectSignScheme(
+ OBJECT *signObject, // IN: signing key
+ TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme
+ );
+TPM_RC
+CryptSign(
+ OBJECT *signKey, // IN: signing key
+ TPMT_SIG_SCHEME *signScheme, // IN: sign scheme.
+ TPM2B_DIGEST *digest, // IN: The digest being signed
+ TPMT_SIGNATURE *signature // OUT: signature
+ );
+TPM_RC
+CryptValidateSignature(
+ TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key
+ TPM2B_DIGEST *digest, // IN: The digest being validated
+ TPMT_SIGNATURE *signature // IN: signature
+ );
+TPM_RC
+CryptGetTestResult(
+ TPM2B_MAX_BUFFER *outData // OUT: test result data
+ );
+TPM_RC
+CryptValidateKeys(
+ TPMT_PUBLIC *publicArea,
+ TPMT_SENSITIVE *sensitive,
+ TPM_RC blamePublic,
+ TPM_RC blameSensitive
+ );
+TPM_RC
+CryptSelectMac(
+ TPMT_PUBLIC *publicArea,
+ TPMI_ALG_MAC_SCHEME *inMac
+ );
+BOOL
+CryptMacIsValidForKey(
+ TPM_ALG_ID keyType,
+ TPM_ALG_ID macAlg,
+ BOOL flag
+ );
+BOOL
+CryptSmacIsValidAlg(
+ TPM_ALG_ID alg,
+ BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid
+ );
+BOOL
+CryptSymModeIsValid(
+ TPM_ALG_ID mode,
+ BOOL flag
+ );
+
+#endif
diff --git a/src/tpm2/crypto/openssl/BnConvert_fp.h b/src/tpm2/crypto/openssl/BnConvert_fp.h
new file mode 100644
index 0000000..dd60da0
--- /dev/null
+++ b/src/tpm2/crypto/openssl/BnConvert_fp.h
@@ -0,0 +1,108 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: BnConvert_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef BNCONVERT_FP_H
+#define BNCONVERT_FP_H
+
+LIB_EXPORT bigNum
+BnFromBytes(
+ bigNum bn,
+ const BYTE *bytes,
+ NUMBYTES nBytes
+ );
+LIB_EXPORT bigNum
+BnFrom2B(
+ bigNum bn, // OUT:
+ const TPM2B *a2B // IN: number to convert
+ );
+LIB_EXPORT bigNum
+BnFromHex(
+ bigNum bn, // OUT:
+ const char *hex // IN:
+ );
+LIB_EXPORT BOOL
+BnToBytes(
+ bigConst bn,
+ BYTE *buffer,
+ NUMBYTES *size // This the number of bytes that are
+ // available in the buffer. The result
+ // should be this big.
+ );
+LIB_EXPORT BOOL
+BnTo2B(
+ bigConst bn, // IN:
+ TPM2B *a2B, // OUT:
+ NUMBYTES size // IN: the desired size
+ );
+LIB_EXPORT bn_point_t *
+BnPointFrom2B(
+ bigPoint ecP, // OUT: the preallocated point structure
+ TPMS_ECC_POINT *p // IN: the number to convert
+ );
+LIB_EXPORT BOOL
+BnPointTo2B(
+ TPMS_ECC_POINT *p, // OUT: the converted 2B structure
+ bigPoint ecP, // IN: the values to be converted
+ bigCurve E // IN: curve descriptor for the point
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/openssl/BnMath_fp.h b/src/tpm2/crypto/openssl/BnMath_fp.h
new file mode 100644
index 0000000..62ba7b2
--- /dev/null
+++ b/src/tpm2/crypto/openssl/BnMath_fp.h
@@ -0,0 +1,163 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: BnMath_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef BNMATH_FP_H
+#define BNMATH_FP_H
+
+LIB_EXPORT BOOL
+BnAdd(
+ bigNum result,
+ bigConst op1,
+ bigConst op2
+ );
+LIB_EXPORT BOOL
+BnAddWord(
+ bigNum result,
+ bigConst op,
+ crypt_uword_t word
+ );
+LIB_EXPORT BOOL
+BnSub(
+ bigNum result,
+ bigConst op1,
+ bigConst op2
+ );
+LIB_EXPORT BOOL
+BnSubWord(
+ bigNum result,
+ bigConst op,
+ crypt_uword_t word
+ );
+LIB_EXPORT int
+BnUnsignedCmp(
+ bigConst op1,
+ bigConst op2
+ );
+LIB_EXPORT int
+BnUnsignedCmpWord(
+ bigConst op1,
+ crypt_uword_t word
+ );
+LIB_EXPORT crypt_word_t
+BnModWord(
+ bigConst numerator,
+ crypt_word_t modulus
+ );
+LIB_EXPORT int
+Msb(
+ crypt_uword_t word
+ );
+LIB_EXPORT int
+BnMsb(
+ bigConst bn
+ );
+LIB_EXPORT unsigned
+BnSizeInBits(
+ bigConst n
+ );
+LIB_EXPORT bigNum
+BnSetWord(
+ bigNum n,
+ crypt_uword_t w
+ );
+LIB_EXPORT BOOL
+BnSetBit(
+ bigNum bn, // IN/OUT: big number to modify
+ unsigned int bitNum // IN: Bit number to SET
+ );
+LIB_EXPORT BOOL
+BnTestBit(
+ bigNum bn, // IN: number to check
+ unsigned int bitNum // IN: bit to test
+ );
+LIB_EXPORT BOOL
+BnMaskBits(
+ bigNum bn, // IN/OUT: number to mask
+ crypt_uword_t maskBit // IN: the bit number for the mask.
+ );
+LIB_EXPORT BOOL
+BnShiftRight(
+ bigNum result,
+ bigConst toShift,
+ uint32_t shiftAmount
+ );
+LIB_EXPORT BOOL
+BnGetRandomBits(
+ bigNum n,
+ size_t bits,
+ RAND_STATE *rand
+ );
+LIB_EXPORT BOOL
+BnGenerateRandomInRange(
+ bigNum dest,
+ bigConst limit,
+ RAND_STATE *rand
+ );
+// libtpms added begin
+LIB_EXPORT BOOL
+BnGenerateRandomInRangeAllBytes(
+ bigNum dest,
+ bigConst limit,
+ RAND_STATE *rand
+ );
+// libtpms added end
+
+#endif
diff --git a/src/tpm2/crypto/openssl/BnMemory_fp.h b/src/tpm2/crypto/openssl/BnMemory_fp.h
new file mode 100644
index 0000000..819a0a6
--- /dev/null
+++ b/src/tpm2/crypto/openssl/BnMemory_fp.h
@@ -0,0 +1,108 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: BnMemory_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef BNMEMORY_FP_H
+#define BNMEMORY_FP_H
+
+LIB_EXPORT bigNum
+BnSetTop(
+ bigNum bn, // IN/OUT: number to clean
+ crypt_uword_t top // IN: the new top
+ );
+#if 0 /* libtpms added */
+LIB_EXPORT bigNum
+BnClearTop(
+ bigNum bn
+ );
+#endif /* libtpms added */
+LIB_EXPORT bigNum
+BnInitializeWord(
+ bigNum bn, // IN:
+ crypt_uword_t allocated, // IN:
+ crypt_uword_t word // IN:
+ );
+LIB_EXPORT bigNum
+BnInit(
+ bigNum bn,
+ crypt_uword_t allocated
+ );
+LIB_EXPORT BOOL
+BnCopy(
+ bigNum out,
+ bigConst in
+ );
+#if 0 /* libtpms added */
+LIB_EXPORT BOOL
+BnPointCopy(
+ bigPoint pOut,
+ pointConst pIn
+ );
+#endif /* libtpms added */
+LIB_EXPORT bn_point_t *
+BnInitializePoint(
+ bigPoint p, // OUT: structure to receive pointers
+ bigNum x, // IN: x coordinate
+ bigNum y, // IN: y coordinate
+ bigNum z // IN: x coordinate
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/openssl/BnValues.h b/src/tpm2/crypto/openssl/BnValues.h
new file mode 100644
index 0000000..1e0164d
--- /dev/null
+++ b/src/tpm2/crypto/openssl/BnValues.h
@@ -0,0 +1,329 @@
+/********************************************************************************/
+/* */
+/* For defining the internal BIGNUM structure */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: BnValues.h 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.1.1 BnValues.h */
+/* This file contains the definitions needed for defining the internal BIGNUM structure. A BIGNUM is
+ a pointer to a structure. The structure has three fields. The last field is and array (d) of
+ crypt_uword_t. Each word is in machine format (big- or little-endian) with the words in ascending
+ significance (i.e. words in little-endian order). This is the order that seems to be used in
+ every big number library in the worlds, so... */
+/* The first field in the structure (allocated) is the number of words in d. This is the upper limit
+ on the size of the number that can be held in the structure. This differs from libraries like
+ OpenSSL() as this is not intended to deal with numbers of arbitrary size; just numbers that are
+ needed to deal with the algorithms that are defined in the TPM implementation. */
+/* The second field in the structure (size) is the number of significant words in n. When this
+ number is zero, the number is zero. The word at used-1 should never be zero. All words between
+ d[size] and d[allocated-1] should be zero. */
+#ifndef _BN_NUMBERS_H
+#define _BN_NUMBERS_H
+#if RADIX_BITS == 64
+# define RADIX_LOG2 6
+#elif RADIX_BITS == 32
+#define RADIX_LOG2 5
+#else
+# error "Unsupported radix"
+#endif
+#define RADIX_MOD(x) ((x) & ((1 << RADIX_LOG2) - 1))
+#define RADIX_DIV(x) ((x) >> RADIX_LOG2)
+#define RADIX_MASK ((((crypt_uword_t)1) << RADIX_LOG2) - 1)
+#define BITS_TO_CRYPT_WORDS(bits) RADIX_DIV((bits) + (RADIX_BITS - 1))
+#define BYTES_TO_CRYPT_WORDS(bytes) BITS_TO_CRYPT_WORDS(bytes * 8)
+#define SIZE_IN_CRYPT_WORDS(thing) BYTES_TO_CRYPT_WORDS(sizeof(thing))
+#if RADIX_BITS == 64
+#define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_64(x)
+typedef uint64_t crypt_uword_t;
+typedef int64_t crypt_word_t;
+# define TO_CRYPT_WORD_64 BIG_ENDIAN_BYTES_TO_UINT64
+# define TO_CRYPT_WORD_32(a, b, c, d) TO_CRYPT_WORD_64(0, 0, 0, 0, a, b, c, d)
+#define BN_PAD 0 /* libtpms added */
+#elif RADIX_BITS == 32
+#define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_32((x))
+typedef uint32_t crypt_uword_t;
+typedef int32_t crypt_word_t;
+# define TO_CRYPT_WORD_64(a, b, c, d, e, f, g, h) \
+ BIG_ENDIAN_BYTES_TO_UINT32(e, f, g, h), \
+ BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d)
+# define TO_CRYPT_WORD_32 BIG_ENDIAN_BYTES_TO_UINT32
+#define BN_PAD 1 /* libtpms added */
+#endif
+#define MAX_CRYPT_UWORD (~((crypt_uword_t)0))
+#define MAX_CRYPT_WORD ((crypt_word_t)(MAX_CRYPT_UWORD >> 1))
+#define MIN_CRYPT_WORD (~MAX_CRYPT_WORD)
+#define LARGEST_NUMBER (MAX((ALG_RSA * MAX_RSA_KEY_BYTES), \
+ MAX((ALG_ECC * MAX_ECC_KEY_BYTES), MAX_DIGEST_SIZE)))
+#define LARGEST_NUMBER_BITS (LARGEST_NUMBER * 8)
+#define MAX_ECC_PARAMETER_BYTES (MAX_ECC_KEY_BYTES * ALG_ECC)
+/* These are the basic big number formats. This is convertible to the library- specific format
+ without too much difficulty. For the math performed using these numbers, the value is always
+ positive. */
+#define BN_STRUCT_DEF(count) struct { \
+ crypt_uword_t allocated; \
+ crypt_uword_t size; \
+ crypt_uword_t d[count + BN_PAD + BN_PAD + BN_PAD]; /* libtpms changed */ \
+ }
+typedef BN_STRUCT_DEF(1) bignum_t;
+#ifndef bigNum
+typedef bignum_t *bigNum;
+typedef const bignum_t *bigConst;
+#endif
+extern const bignum_t BnConstZero;
+/* The Functions to access the properties of a big number. Get number of allocated words */
+#define BnGetAllocated(x) (unsigned)((x)->allocated)
+/* Get number of words used */
+#define BnGetSize(x) ((x)->size)
+/* Get a pointer to the data array */
+#define BnGetArray(x) ((crypt_uword_t *)&((x)->d[0]))
+/* Get the nth word of a BIGNUM (zero-based) */
+#define BnGetWord(x, i) (crypt_uword_t)((x)->d[i])
+/* Some things that are done often. Test to see if a bignum_t is equal to zero */
+#define BnEqualZero(bn) (BnGetSize(bn) == 0)
+/* Test to see if a bignum_t is equal to a word type */
+#define BnEqualWord(bn, word) \
+ ((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word))
+/* Determine if a BIGNUM is even. A zero is even. Although the indication that a number is zero is
+ that its size is zero, all words of the number are 0 so this test works on zero. */
+#define BnIsEven(n) ((BnGetWord(n, 0) & 1) == 0)
+/* The macros below are used to define BIGNUM values of the required size. The values are allocated
+ on the stack so they can be treated like simple local values. This will call the initialization
+ function for a defined bignum_t. This sets the allocated and used fields and clears the words of
+ n. */
+#define BN_INIT(name) \
+ (bigNum)BnInit((bigNum)&(name), \
+ BYTES_TO_CRYPT_WORDS(sizeof(name.d)))
+/* In some cases, a function will need the address of the structure associated with a variable. The
+ structure for a BIGNUM variable of name is name_. Generally, when the structure is created, it is
+ initialized and a parameter is created with a pointer to the structure. The pointer has the name
+ and the structure it points to is name_ */
+#define BN_ADDRESS(name) (bigNum)&name##_
+
+#define BN_CONST(name, words, initializer) \
+ typedef const struct name##_type { \
+ crypt_uword_t allocated; \
+ crypt_uword_t size; \
+ crypt_uword_t d[words < 1 ? 1 : words]; \
+ } name##_type; \
+ name##_type name = {(words < 1 ? 1 : words), words, {initializer}};
+
+#define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1)
+/* Create a structure of the correct size. */
+#define BN_STRUCT(bits) \
+ BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits))
+/* Define a BIGNUM type with a specific allocation */
+#define BN_TYPE(name, bits) \
+ typedef BN_STRUCT(bits) bn_##name##_t
+/* This creates a local BIGNUM variable of a specific size and initializes it from a TPM2B input
+ parameter. */
+#define BN_INITIALIZED(name, bits, initializer) \
+ BN_STRUCT(bits) name##_; \
+ bigNum name = BnFrom2B(BN_INIT(name##_), \
+ (const TPM2B *)initializer)
+/* Create a local variable that can hold a number with bits */
+#define BN_VAR(name, bits) \
+ BN_STRUCT(bits) _##name; \
+ bigNum name = BN_INIT(_##name)
+/* Create a type that can hold the largest number defined by the implementation. */
+#define BN_MAX(name) BN_VAR(name, LARGEST_NUMBER_BITS)
+#define BN_MAX_INITIALIZED(name, initializer) \
+ BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer)
+/* A word size value is useful */
+#define BN_WORD(name) BN_VAR(name, RADIX_BITS)
+/* This is used to create a word-size BIGNUM and initialize it with an input parameter to a
+ function. */
+#define BN_WORD_INITIALIZED(name, initial) \
+ BN_STRUCT(RADIX_BITS) name##_; \
+ bigNum name = BnInitializeWord((bigNum)&name##_, \
+ BN_STRUCT_ALLOCATION(RADIX_BITS), initial)
+/* ECC-Specific Values This is the format for a point. It is always in affine format. The Z value is
+ carried as part of the point, primarily to simplify the interface to the support library. Rather
+ than have the interface layer have to create space for the point each time it is used... The x,
+ y, and z values are pointers to bigNum values and not in-line versions of the numbers. This is a
+ relic of the days when there was no standard TPM format for the numbers */
+typedef struct _bn_point_t
+{
+ bigNum x;
+ bigNum y;
+ bigNum z;
+} bn_point_t;
+typedef bn_point_t *bigPoint;
+typedef const bn_point_t *pointConst;
+typedef struct constant_point_t
+{
+ bigConst x;
+ bigConst y;
+ bigConst z;
+} constant_point_t;
+#define ECC_BITS (MAX_ECC_KEY_BYTES * 8)
+BN_TYPE(ecc, ECC_BITS);
+#define ECC_NUM(name) BN_VAR(name, ECC_BITS)
+#define ECC_INITIALIZED(name, initializer) \
+ BN_INITIALIZED(name, ECC_BITS, initializer)
+#define POINT_INSTANCE(name, bits) \
+ BN_STRUCT (bits) name##_x = \
+ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \
+ BN_STRUCT ( bits ) name##_y = \
+ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \
+ BN_STRUCT ( bits ) name##_z = \
+ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \
+ bn_point_t name##_
+#define POINT_INITIALIZER(name) \
+ BnInitializePoint(&name##_, (bigNum)&name##_x, \
+ (bigNum)&name##_y, (bigNum)&name##_z)
+#define POINT_INITIALIZED(name, initValue) \
+ POINT_INSTANCE(name, MAX_ECC_KEY_BITS); \
+ bigPoint name = BnPointFrom2B( \
+ POINT_INITIALIZER(name), \
+ initValue)
+#define POINT_VAR(name, bits) \
+ POINT_INSTANCE (name, bits); \
+ bigPoint name = POINT_INITIALIZER(name)
+#define POINT(name) POINT_VAR(name, MAX_ECC_KEY_BITS)
+/* Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC */
+typedef struct
+{
+ bigConst prime; // a prime number
+ bigConst order; // the order of the curve
+ bigConst h; // cofactor
+ bigConst a; // linear coefficient
+ bigConst b; // constant term
+ constant_point_t base; // base point
+} ECC_CURVE_DATA;
+/* Access macros for the ECC_CURVE structure. The parameter C is a pointer to an ECC_CURVE_DATA
+ structure. In some libraries, the curve structure contains a pointer to an ECC_CURVE_DATA
+ structure as well as some other bits. For those cases, the AccessCurveData() macro is used in the
+ code to first get the pointer to the ECC_CURVE_DATA for access. In some cases, the macro does
+ nothing. */
+#define CurveGetPrime(C) ((C)->prime)
+#define CurveGetOrder(C) ((C)->order)
+#define CurveGetCofactor(C) ((C)->h)
+#define CurveGet_a(C) ((C)->a)
+#define CurveGet_b(C) ((C)->b)
+#define CurveGetG(C) ((pointConst)&((C)->base))
+#define CurveGetGx(C) ((C)->base.x)
+#define CurveGetGy(C) ((C)->base.y)
+/* Convert bytes in initializers according to the endianness of the system. This is used for
+ CryptEccData.c. */
+#define BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) \
+ ( ((UINT32)(a) << 24) \
+ + ((UINT32)(b) << 16) \
+ + ((UINT32)(c) << 8) \
+ + ((UINT32)(d)) \
+ )
+#define BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h) \
+ ( ((UINT64)(a) << 56) \
+ + ((UINT64)(b) << 48) \
+ + ((UINT64)(c) << 40) \
+ + ((UINT64)(d) << 32) \
+ + ((UINT64)(e) << 24) \
+ + ((UINT64)(f) << 16) \
+ + ((UINT64)(g) << 8) \
+ + ((UINT64)(h)) \
+ )
+
+#ifndef RADIX_BYTES
+# if RADIX_BITS == 32
+# define RADIX_BYTES 4
+# elif RADIX_BITS == 64
+# define RADIX_BYTES 8
+# else
+# error "RADIX_BITS must either be 32 or 64"
+# endif
+#endif
+
+/* These macros are used for data initialization of big number ECC constants These two macros
+ combine a macro for data definition with a macro for structure initialization. The a parameter is
+ a macro that gives numbers to each of the bytes of the initializer and defines where each of the
+ numberd bytes will show up in the final structure. The b value is a structure that contains the
+ requisite number of bytes in big endian order. S, the MJOIN and JOIND macros will combine a macro
+ defining a data layout with a macro defining the data to be places. Generally, these macros will
+ only need expansion when CryptEccData().c gets compiled. */
+#define JOINED(a,b) a b
+#define MJOIN(a,b) a b
+
+#define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d)
+#if RADIX_BYTES == 64
+#define B8_TO_BN(a, b, c, d, e, f, g, h) \
+ (UINT64)(((((((((((((((a) << 8) | b) << 8) | c) << 8) | d) << 8) \
+ e) << 8) | f) << 8) | g) << 8) | h)
+#define B1_TO_BN(a) B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a)
+#define B2_TO_BN(a, b) B8_TO_BN(0, 0, 0, 0, 0, 0, a, b)
+#define B3_TO_BN(a, b, c) B8_TO_BN(0, 0, 0, 0, 0, a, b, c)
+#define B4_TO_BN(a, b, c, d) B8_TO_BN(0, 0, 0, 0, a, b, c, d)
+#define B5_TO_BN(a, b, c, d, e) B8_TO_BN(0, 0, 0, a, b, c, d, e)
+#define B6_TO_BN(a, b, c, d, e, f) B8_TO_BN(0, 0, a, b, c, d, e, f)
+#define B7_TO_BN(a, b, c, d, e, f, g) B8_TO_BN(0, a, b, c, d, e, f, g)
+#else
+#define B1_TO_BN(a) B4_TO_BN(0, 0, 0, a)
+#define B2_TO_BN(a, b) B4_TO_BN(0, 0, a, b)
+#define B3_TO_BN(a, b, c) B4_TO_BN(0, a, b, c)
+#define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d)
+#define B5_TO_BN(a, b, c, d, e) B4_TO_BN(b, c, d, e), B1_TO_BN(a)
+#define B6_TO_BN(a, b, c, d, e, f) B4_TO_BN(c, d, e, f), B2_TO_BN(a, b)
+#define B7_TO_BN(a, b, c, d, e, f, g) B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c)
+#define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d)
+
+#endif
+
+/* Add implementation dependent definitions for other ECC Values and for linkages */
+
+#include LIB_INCLUDE(MATH_LIB, Math)
+
+#endif // _BN_NUMBERS_H
+
diff --git a/src/tpm2/crypto/openssl/ConsttimeUtils.h b/src/tpm2/crypto/openssl/ConsttimeUtils.h
new file mode 100644
index 0000000..3364bee
--- /dev/null
+++ b/src/tpm2/crypto/openssl/ConsttimeUtils.h
@@ -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 (admin@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 --git a/src/tpm2/crypto/openssl/CryptCmac.c b/src/tpm2/crypto/openssl/CryptCmac.c
new file mode 100644
index 0000000..0461e78
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptCmac.c
@@ -0,0 +1,210 @@
+/********************************************************************************/
+/* */
+/* Message Authentication Codes Based on a Symmetric Block Cipher */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptCmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2018 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.6 CryptCmac.c */
+/* 10.2.6.1 Introduction */
+/* This file contains the implementation of the message authentication codes based on a symmetric
+ block cipher. These functions only use the single block encryption functions of the selected
+ symmetric cryptographic library. */
+/* 10.2.6.2 Includes, Defines, and Typedefs */
+#define _CRYPT_HASH_C_
+#include "Tpm.h"
+#include "CryptSym.h"
+#if ALG_CMAC
+ /* 10.2.6.3 Functions */
+ /* 10.2.6.3.1 CryptCmacStart() */
+ /* This is the function to start the CMAC sequence operation. It initializes the dispatch
+ functions for the data and end operations for CMAC and initializes the parameters that are
+ used for the processing of data, including the key, key size and block cipher algorithm. */
+UINT16
+CryptCmacStart(
+ SMAC_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParms,
+ TPM_ALG_ID macAlg,
+ TPM2B *key
+ )
+{
+ tpmCmacState_t *cState = &state->state.cmac;
+ TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym;
+ //
+ if(macAlg != TPM_ALG_CMAC)
+ return 0;
+ MemorySet(cState, 0, sizeof(*cState)); // libtpms bugfix
+ // set up the encryption algorithm and parameters
+ cState->symAlg = def->algorithm;
+ cState->keySizeBits = def->keyBits.sym;
+ cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm,
+ def->keyBits.sym);
+ MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer));
+ // Set up the dispatch methods for the CMAC
+ state->smacMethods.data = CryptCmacData;
+ state->smacMethods.end = CryptCmacEnd;
+ return cState->iv.t.size;
+}
+
+/* 10.2.5.3.2 CryptCmacData() */
+/* This function is used to add data to the CMAC sequence computation. The function will XOR new
+ data into the IV. If the buffer is full, and there is additional input data, the data is
+ encrypted into the IV buffer, the new data is then XOR into the IV. When the data runs out, the
+ function returns without encrypting even if the buffer is full. The last data block of a sequence
+ will not be encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey to be
+ computed and applied before the last block is encrypted. */
+void
+CryptCmacData(
+ SMAC_STATES *state,
+ UINT32 size,
+ const BYTE *buffer
+ )
+{
+ tpmCmacState_t *cmacState = &state->cmac;
+ TPM_ALG_ID algorithm = cmacState->symAlg;
+ BYTE *key = cmacState->symKey.t.buffer;
+ UINT16 keySizeInBits = cmacState->keySizeBits;
+ tpmCryptKeySchedule_t keySchedule;
+ TpmCryptSetSymKeyCall_t encrypt;
+ //
+ memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */
+ // Set up the encryption values based on the algorithm
+ switch (algorithm)
+ {
+ FOR_EACH_SYM(ENCRYPT_CASE)
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+ while(size > 0)
+ {
+ if(cmacState->bcount == cmacState->iv.t.size)
+ {
+ ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer);
+ cmacState->bcount = 0;
+ }
+ for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size);
+ size--, cmacState->bcount++)
+ {
+ cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++;
+ }
+ }
+}
+
+/* 10.2.6.3.3 CryptCmacEnd() */
+/* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey
+ to be applied before the last block is encrypted. */
+UINT16
+CryptCmacEnd(
+ SMAC_STATES *state,
+ UINT32 outSize,
+ BYTE *outBuffer
+ )
+{
+ tpmCmacState_t *cState = &state->cmac;
+ // Need to set algorithm, key, and keySizeInBits in the local context so that
+ // the SELECT and ENCRYPT macros will work here
+ TPM_ALG_ID algorithm = cState->symAlg;
+ BYTE *key = cState->symKey.t.buffer;
+ UINT16 keySizeInBits = cState->keySizeBits;
+ tpmCryptKeySchedule_t keySchedule;
+ TpmCryptSetSymKeyCall_t encrypt;
+ TPM2B_IV subkey = {{0, {0}}};
+ BOOL xorVal;
+ UINT16 i;
+ memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */
+
+ subkey.t.size = cState->iv.t.size;
+ // Encrypt a block of zero
+ // Set up the encryption values based on the algorithm
+ switch (algorithm)
+ {
+ FOR_EACH_SYM(ENCRYPT_CASE)
+ default:
+ return 0;
+ }
+ ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer);
+
+ // shift left by 1 and XOR with 0x0...87 if the MSb was 0
+ xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
+ ShiftLeft(&subkey.b);
+ subkey.t.buffer[subkey.t.size - 1] ^= xorVal;
+ // this is a sanity check to make sure that the algorithm is working properly.
+ // remove this check when debug is done
+ pAssert(cState->bcount <= cState->iv.t.size);
+ // If the buffer is full then no need to compute subkey 2.
+ if(cState->bcount < cState->iv.t.size)
+ {
+ //Pad the data
+ cState->iv.t.buffer[cState->bcount++] ^= 0x80;
+ // The rest of the data is a pad of zero which would simply be XORed
+ // with the iv value so nothing to do...
+ // Now compute K2
+ xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
+ ShiftLeft(&subkey.b);
+ subkey.t.buffer[subkey.t.size - 1] ^= xorVal;
+ }
+ // XOR the subkey into the IV
+ for(i = 0; i < subkey.t.size; i++)
+ cState->iv.t.buffer[i] ^= subkey.t.buffer[i];
+ ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer);
+ i = (UINT16)MIN(cState->iv.t.size, outSize);
+ MemoryCopy(outBuffer, cState->iv.t.buffer, i);
+
+ return i;
+}
+
+#endif
diff --git a/src/tpm2/crypto/openssl/CryptDes.c b/src/tpm2/crypto/openssl/CryptDes.c
new file mode 100644
index 0000000..9efa3ce
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptDes.c
@@ -0,0 +1,189 @@
+/********************************************************************************/
+/* */
+/* Functions Required for TDES */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptDes.c 1398 2018-12-17 22:37:57Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2018 */
+/* */
+/********************************************************************************/
+
+/* 10.2.9 CryptDes.c */
+/* 10.2.9.1 Introduction */
+/* This file contains the extra functions required for TDES. */
+/* 10.2.9.2 Includes, Defines, and Typedefs */
+#include "Tpm.h"
+#include "Helpers_fp.h" // libtpms added
+#if ALG_TDES
+#define DES_NUM_WEAK 64
+const UINT64 DesWeakKeys[DES_NUM_WEAK] = {
+ 0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL, 0xE0E0E0E0F1F1F1F1ULL, 0x1F1F1F1F0E0E0E0EULL,
+ 0x011F011F010E010EULL, 0x1F011F010E010E01ULL, 0x01E001E001F101F1ULL, 0xE001E001F101F101ULL,
+ 0x01FE01FE01FE01FEULL, 0xFE01FE01FE01FE01ULL, 0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL,
+ 0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL, 0xE0FEE0FEF1FEF1FEULL, 0xFEE0FEE0FEF1FEF1ULL,
+ 0x01011F1F01010E0EULL, 0x1F1F01010E0E0101ULL, 0xE0E01F1FF1F10E0EULL, 0x0101E0E00101F1F1ULL,
+ 0x1F1FE0E00E0EF1F1ULL, 0xE0E0FEFEF1F1FEFEULL, 0x0101FEFE0101FEFEULL, 0x1F1FFEFE0E0EFEFEULL,
+ 0xE0FE011FF1FE010EULL, 0x011F1F01010E0E01ULL, 0x1FE001FE0EF101FEULL, 0xE0FE1F01F1FE0E01ULL,
+ 0x011FE0FE010EF1FEULL, 0x1FE0E01F0EF1F10EULL, 0xE0FEFEE0F1FEFEF1ULL, 0x011FFEE0010EFEF1ULL,
+ 0x1FE0FE010EF1FE01ULL, 0xFE0101FEFE0101FEULL, 0x01E01FFE01F10EFEULL, 0x1FFE01E00EFE01F1ULL,
+ 0xFE011FE0FE010EF1ULL, 0xFE01E01FFE01F10EULL, 0x1FFEE0010EFEF101ULL, 0xFE1F01E0FE0E01F1ULL,
+ 0x01E0E00101F1F101ULL, 0x1FFEFE1F0EFEFE0EULL, 0xFE1FE001FE0EF101ULL, 0x01E0FE1F01F1FE0EULL,
+ 0xE00101E0F10101F1ULL, 0xFE1F1FFEFE0E0EFEULL, 0x01FE1FE001FE0EF1ULL, 0xE0011FFEF1010EFEULL,
+ 0xFEE0011FFEF1010EULL, 0x01FEE01F01FEF10EULL, 0xE001FE1FF101FE0EULL, 0xFEE01F01FEF10E01ULL,
+ 0x01FEFE0101FEFE01ULL, 0xE01F01FEF10E01FEULL, 0xFEE0E0FEFEF1F1FEULL, 0x1F01011F0E01010EULL,
+ 0xE01F1FE0F10E0EF1ULL, 0xFEFE0101FEFE0101ULL, 0x1F01E0FE0E01F1FEULL, 0xE01FFE01F10EFE01ULL,
+ 0xFEFE1F1FFEFE0E0EULL, 0x1F01FEE00E01FEF1ULL, 0xE0E00101F1F10101ULL, 0xFEFEE0E0FEFEF1F1ULL};
+/* 10.2.9.2.1 CryptSetOddByteParity() */
+/* This function sets the per byte parity of a 64-bit value. The least-significant bit is of each
+ byte is replaced with the odd parity of the other 7 bits in the byte. With odd parity, no byte
+ will ever be 0x00. */
+UINT64
+CryptSetOddByteParity(
+ UINT64 k
+ )
+{
+#define PMASK 0x0101010101010101ULL
+ UINT64 out;
+ k |= PMASK; // set the parity bit
+ out = k;
+ k ^= k >> 4;
+ k ^= k >> 2;
+ k ^= k >> 1;
+ k &= PMASK; // odd parity extracted
+ out ^= k; // out is now even parity because parity bit was already set
+ out ^= PMASK; // out is now even parity
+ return out;
+}
+/* 10.2.9.2.2 CryptDesIsWeakKey() */
+/* Check to see if a DES key is on the list of weak, semi-weak, or possibly weak keys. */
+/* Return Value Meaning */
+/* TRUE(1) DES key is weak */
+/* FALSE(0) DES key is not weak */
+static BOOL
+CryptDesIsWeakKey(
+ UINT64 k
+ )
+{
+ int i;
+ //
+ for(i = 0; i < DES_NUM_WEAK; i++)
+ {
+ if(k == DesWeakKeys[i])
+ return TRUE;
+ }
+ return FALSE;
+}
+/* 10.2.9.2.3 CryptDesValidateKey() */
+/* Function to check to see if the input key is a valid DES key where the definition of valid is
+ that none of the elements are on the list of weak, semi-weak, or possibly weak keys; and that for
+ two keys, K1!=K2, and for three keys that K1!=K2 and K2!=K3. */
+BOOL
+CryptDesValidateKey(
+ TPM2B_SYM_KEY *desKey // IN: key to validate
+ )
+{
+ UINT64 k[3];
+ int i;
+ int keys = (desKey->t.size + 7) / 8;
+ BYTE *pk = desKey->t.buffer;
+ BOOL ok;
+ //
+ // Note: 'keys' is the number of keys, not the maximum index for 'k'
+ ok = ((keys == 2) || (keys == 3)) && ((desKey->t.size % 8) == 0);
+ for(i = 0; ok && i < keys; pk += 8, i++)
+ {
+ k[i] = CryptSetOddByteParity(BYTE_ARRAY_TO_UINT64(pk));
+ ok = !CryptDesIsWeakKey(k[i]);
+ }
+ ok = ok && k[0] != k[1];
+ if(keys == 3)
+ ok = ok && k[1] != k[2];
+ return ok;
+}
+/* 10.2.9.2.4 CryptGenerateKeyDes() */
+/* This function is used to create a DES key of the appropriate size. The key will have odd parity
+ in the bytes. */
+TPM_RC
+CryptGenerateKeyDes(
+ TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
+ // for the new key.
+ TPMT_SENSITIVE *sensitive, // OUT: sensitive area
+ RAND_STATE *rand // IN: the "entropy" source for
+ )
+{
+ // Assume that the publicArea key size has been validated and is a supported
+ // number of bits.
+ sensitive->sensitive.sym.t.size =
+ BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym);
+#if USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added begin
+ if (rand == NULL)
+ return OpenSSLCryptGenerateKeyDes(sensitive);
+#endif // libtpms added end
+ do
+ {
+ BYTE *pK = sensitive->sensitive.sym.t.buffer;
+ int i = (sensitive->sensitive.sym.t.size + 7) / 8;
+ // Use the random number generator to generate the required number of bits
+ if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0)
+ return TPM_RC_NO_RESULT;
+ for(; i > 0; pK += 8, i--)
+ {
+ UINT64 k = BYTE_ARRAY_TO_UINT64(pK);
+ k = CryptSetOddByteParity(k);
+ UINT64_TO_BYTE_ARRAY(k, pK);
+ }
+ } while(!CryptDesValidateKey(&sensitive->sensitive.sym));
+ return TPM_RC_SUCCESS;
+}
+#endif
diff --git a/src/tpm2/crypto/openssl/CryptEccKeyExchange.c b/src/tpm2/crypto/openssl/CryptEccKeyExchange.c
new file mode 100644
index 0000000..4d1fccb
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptEccKeyExchange.c
@@ -0,0 +1,373 @@
+/********************************************************************************/
+/* */
+/* Functions that are used for the two-phase, ECC, key-exchange protocols */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccKeyExchange.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.11 CryptEccKeyExchange.c */
+#include "Tpm.h"
+
+LIB_EXPORT TPM_RC
+SM2KeyExchange(
+ TPMS_ECC_POINT *outZ, // OUT: the computed point
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsBIn, // IN: static public party B key
+ TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key
+ );
+
+#if CC_ZGen_2Phase == YES
+#if ALG_ECMQV
+/* 10.2.11.1.1 avf1() */
+/* This function does the associated value computation required by MQV key exchange. Process: */
+/* a) Convert xQ to an integer xqi using the convention specified in Appendix C.3. */
+/* b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). */
+/* c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) */
+/* Always returns TRUE(1). */
+static BOOL
+avf1(
+ bigNum bnX, // IN/OUT: the reduced value
+ bigNum bnN // IN: the order of the curve
+ )
+{
+ // compute f = 2^(ceil(ceil(log2(n)) / 2))
+ int f = (BnSizeInBits(bnN) + 1) / 2;
+ // x' = 2^f + (x mod 2^f)
+ BnMaskBits(bnX, f); // This is mod 2*2^f but it doesn't matter because
+ // the next operation will SET the extra bit anyway
+ BnSetBit(bnX, f);
+ return TRUE;
+}
+/* 10.2.11.1.2 C_2_2_MQV() */
+/* This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC
+ MQV). */
+/* CAUTION: Implementation of this function may require use of essential claims in patents not owned
+ by TCG members. */
+/* Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly
+ catastrophically, if this is not the case. */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */
+static TPM_RC
+C_2_2_MQV(
+ TPMS_ECC_POINT *outZ, // OUT: the computed point
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsB, // IN: static public party B key
+ TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ const ECC_CURVE_DATA *C;
+ POINT(pQeA);
+ POINT_INITIALIZED(pQeB, QeB);
+ POINT_INITIALIZED(pQsB, QsB);
+ ECC_NUM(bnTa);
+ ECC_INITIALIZED(bnDeA, deA);
+ ECC_INITIALIZED(bnDsA, dsA);
+ ECC_NUM(bnN);
+ ECC_NUM(bnXeB);
+ TPM_RC retVal;
+ //
+ // Parameter checks
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+ pAssert(outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL
+ && dsA != NULL);
+ C = AccessCurveData(E);
+ // Process:
+ // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
+ // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
+ // 3. If P = O, output an error indicator.
+ // 4. Z=xP, where xP is the x-coordinate of P.
+ // Compute the public ephemeral key pQeA = [de,A]G
+ if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E))
+ != TPM_RC_SUCCESS)
+ goto Exit;
+ // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
+ // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
+ // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n
+ // Ta = avf(XeA);
+ BnCopy(bnTa, pQeA->x);
+ avf1(bnTa, bnN);
+ // do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
+ BnModMult(bnTa, bnDsA, bnTa, bnN);
+ // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
+ BnAdd(bnTa, bnTa, bnDeA);
+ BnMod(bnTa, bnN);
+ // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
+ // Put this in because almost every case of h is == 1 so skip the call when
+ // not necessary.
+ if(!BnEqualWord(CurveGetCofactor(C), 1))
+ // Cofactor is not 1 so compute Ta := Ta * h mod n
+ BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C));
+ // Now that 'tA' is (h * 'tA' mod n)
+ // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
+ // first, compute XeB = avf(XeB)
+ avf1(bnXeB, bnN);
+ // QsB := [XeB]QsB
+ BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E);
+ BnEccAdd(pQeB, pQeB, pQsB, E);
+ // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
+ // If the result is not the point at infinity, return QeB
+ BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E);
+ if(BnEqualZero(pQeB->z))
+ ERROR_RETURN(TPM_RC_NO_RESULT);
+ // Convert BIGNUM E to TPM2B E
+ BnPointTo2B(outZ, pQeB, E);
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+#endif // ALG_ECMQV
+/* 10.2.11.1.3 C_2_2_ECDH() */
+/* This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified
+ Model, C(2, 2, ECC CDH). */
+static TPM_RC
+C_2_2_ECDH(
+ TPMS_ECC_POINT *outZs, // OUT: Zs
+ TPMS_ECC_POINT *outZe, // OUT: Ze
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsB, // IN: static public party B key
+ TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ ECC_INITIALIZED(bnAs, dsA);
+ ECC_INITIALIZED(bnAe, deA);
+ POINT_INITIALIZED(ecBs, QsB);
+ POINT_INITIALIZED(ecBe, QeB);
+ POINT(ecZ);
+ TPM_RC retVal;
+ //
+ // Parameter checks
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_CURVE);
+ pAssert(outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL
+ && QeB != NULL);
+ // Do the point multiply for the Zs value ([dsA]QsB)
+ retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E);
+ if(retVal == TPM_RC_SUCCESS)
+ {
+ // Convert the Zs value.
+ BnPointTo2B(outZs, ecZ, E);
+ // Do the point multiply for the Ze value ([deA]QeB)
+ retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E);
+ if(retVal == TPM_RC_SUCCESS)
+ BnPointTo2B(outZe, ecZ, E);
+ }
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+/* 10.2.11.1.4 CryptEcc2PhaseKeyExchange() */
+/* This function is the dispatch routine for the EC key exchange functions that use two ephemeral
+ and two static keys. */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME scheme is not defined */
+LIB_EXPORT TPM_RC
+CryptEcc2PhaseKeyExchange(
+ TPMS_ECC_POINT *outZ1, // OUT: a computed point
+ TPMS_ECC_POINT *outZ2, // OUT: and optional second point
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM_ALG_ID scheme, // IN: the key exchange scheme
+ TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsB, // IN: static public party B key
+ TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
+ )
+{
+ pAssert(outZ1 != NULL
+ && dsA != NULL && deA != NULL
+ && QsB != NULL && QeB != NULL);
+ // Initialize the output points so that they are empty until one of the
+ // functions decides otherwise
+ outZ1->x.b.size = 0;
+ outZ1->y.b.size = 0;
+ if(outZ2 != NULL)
+ {
+ outZ2->x.b.size = 0;
+ outZ2->y.b.size = 0;
+ }
+ switch(scheme)
+ {
+ case TPM_ALG_ECDH:
+ return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
+ break;
+#if ALG_ECMQV
+ case TPM_ALG_ECMQV:
+ return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
+ break;
+#endif
+#if ALG_SM2
+ case TPM_ALG_SM2:
+ return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB);
+ break;
+#endif
+ default:
+ return TPM_RC_SCHEME;
+ }
+}
+#if ALG_SM2
+/* 10.2.11.1.5 ComputeWForSM2() */
+/* Compute the value for w used by SM2 */
+static UINT32
+ComputeWForSM2(
+ bigCurve E
+ )
+{
+ // w := ceil(ceil(log2(n)) / 2) - 1
+ return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1);
+}
+/* 10.2.11.1.6 avfSm2() */
+/* This function does the associated value computation required by SM2 key exchange. This is
+ different form the avf() in the international standards because it returns a value that is half
+ the size of the value returned by the standard avf. For example, if n is 15, Ws (w in the
+ standard) is 2 but the W here is 1. This means that an input value of 14 (1110b) would return a
+ value of 110b with the standard but 10b with the scheme in SM2. */
+static bigNum
+avfSm2(
+ bigNum bn, // IN/OUT: the reduced value
+ UINT32 w // IN: the value of w
+ )
+{
+ // a) set w := ceil(ceil(log2(n)) / 2) - 1
+ // b) set x' := 2^w + ( x & (2^w - 1))
+ // This is just like the avf for MQV where x' = 2^w + (x mod 2^w)
+ BnMaskBits(bn, w); // as with avf1, this is too big by a factor of 2 but
+ // it doesn't matter because we SET the extra bit
+ // anyway
+ BnSetBit(bn, w);
+ return bn;
+}
+/* SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to
+ compute tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA
+ + [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral
+ private key. All points are required to be on the curve of inQsA. The function will fail
+ catastrophically if this is not the case */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */
+LIB_EXPORT TPM_RC
+SM2KeyExchange(
+ TPMS_ECC_POINT *outZ, // OUT: the computed point
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key
+ TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key
+ TPMS_ECC_POINT *QsBIn, // IN: static public party B key
+ TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ const ECC_CURVE_DATA *C;
+ ECC_INITIALIZED(dsA, dsAIn);
+ ECC_INITIALIZED(deA, deAIn);
+ POINT_INITIALIZED(QsB, QsBIn);
+ POINT_INITIALIZED(QeB, QeBIn);
+ BN_WORD_INITIALIZED(One, 1);
+ POINT(QeA);
+ ECC_NUM(XeB);
+ POINT(Z);
+ ECC_NUM(Ta);
+ UINT32 w;
+ TPM_RC retVal = TPM_RC_NO_RESULT;
+ //
+ // Parameter checks
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_CURVE);
+ C = AccessCurveData(E);
+ pAssert(outZ != NULL && dsA != NULL && deA != NULL && QsB != NULL
+ && QeB != NULL);
+ // Compute the value for w
+ w = ComputeWForSM2(E);
+ // Compute the public ephemeral key pQeA = [de,A]G
+ if(!BnEccModMult(QeA, CurveGetG(C), deA, E))
+ goto Exit;
+ // tA := (ds,A + de,A avf(Xe,A)) mod n (3)
+ // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n
+ // Ta = avf(XeA);
+ // do Ta = de,A * Ta = deA * avf(XeA)
+ BnMult(Ta, deA, avfSm2(QeA->x, w));
+ // now Ta = dsA + Ta = dsA + deA * avf(XeA)
+ BnAdd(Ta, dsA, Ta);
+ BnMod(Ta, CurveGetOrder(C));
+ // outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4)
+ // Put this in because almost every case of h is == 1 so skip the call when
+ // not necessary.
+ if(!BnEqualWord(CurveGetCofactor(C), 1))
+ // Cofactor is not 1 so compute Ta := Ta * h mod n
+ BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C));
+ // Now that 'tA' is (h * 'tA' mod n)
+ // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)).
+ BnCopy(XeB, QeB->x);
+ if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E))
+ goto Exit;
+ // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
+ if(!BnEccModMult(Z, Z, Ta, E))
+ goto Exit;
+ // Convert BIGNUM E to TPM2B E
+ BnPointTo2B(outZ, Z, E);
+ retVal = TPM_RC_SUCCESS;
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+#endif
+#endif // CC_ZGen_2Phase
diff --git a/src/tpm2/crypto/openssl/CryptEccMain.c b/src/tpm2/crypto/openssl/CryptEccMain.c
new file mode 100644
index 0000000..be92831
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptEccMain.c
@@ -0,0 +1,866 @@
+/********************************************************************************/
+/* */
+/* ECC Main */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccMain.c 1519 2019-11-15 20:43:51Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+/* 10.2.11 CryptEccMain.c */
+/* 10.2.11.1 Includes and Defines */
+#include "Tpm.h"
+#include "Helpers_fp.h" // libtpms added
+#include "TpmToOsslMath_fp.h" // libtpms added
+#if ALG_ECC
+/* This version requires that the new format for ECC data be used */
+#if !USE_BN_ECC_DATA
+#error "Need to SET USE_BN_ECC_DATA to YES in TpmBuildSwitches.h"
+#endif
+/* 10.2.11.2 Functions */
+#if SIMULATION
+void
+EccSimulationEnd(
+ void
+ )
+{
+#if SIMULATION
+ // put things to be printed at the end of the simulation here
+#endif
+}
+#endif // SIMULATION
+/* 10.2.11.2.1 CryptEccInit() */
+/* This function is called at _TPM_Init() */
+BOOL
+CryptEccInit(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.11.2.2 CryptEccStartup() */
+/* This function is called at TPM2_Startup(). */
+BOOL
+CryptEccStartup(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.11.2.3 ClearPoint2B(generic */
+/* Initialize the size values of a TPMS_ECC_POINT structure. */
+void
+ClearPoint2B(
+ TPMS_ECC_POINT *p // IN: the point
+ )
+{
+ if(p != NULL)
+ {
+ p->x.t.size = 0;
+ p->y.t.size = 0;
+ }
+}
+/* 10.2.11.2.4 CryptEccGetParametersByCurveId() */
+/* This function returns a pointer to the curve data that is associated with the indicated
+ curveId. If there is no curve with the indicated ID, the function returns NULL. This function is
+ in this module so that it can be called by GetCurve() data. */
+/* Return Values Meaning */
+/* NULL curve with the indicated TPM_ECC_CURVE is not implemented */
+/* non-NULL pointer to the curve data */
+LIB_EXPORT const ECC_CURVE *
+CryptEccGetParametersByCurveId(
+ TPM_ECC_CURVE curveId // IN: the curveID
+ )
+{
+ int i;
+ for(i = 0; i < ECC_CURVE_COUNT; i++)
+ {
+ if(eccCurves[i].curveId == curveId)
+ return &eccCurves[i];
+ }
+ return NULL;
+}
+/* 10.2.11.2.5 CryptEccGetKeySizeForCurve() */
+/* This function returns the key size in bits of the indicated curve */
+LIB_EXPORT UINT16
+CryptEccGetKeySizeForCurve(
+ TPM_ECC_CURVE curveId // IN: the curve
+ )
+{
+ const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
+ UINT16 keySizeInBits;
+ //
+ keySizeInBits = (curve != NULL) ? curve->keySizeBits : 0;
+ return keySizeInBits;
+}
+/* 10.2.11.2.6 GetCurveData() */
+/* This function returns the a pointer for the parameter data associated with a curve. */
+const ECC_CURVE_DATA *
+GetCurveData(
+ TPM_ECC_CURVE curveId // IN: the curveID
+ )
+{
+ const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
+ return (curve != NULL) ? curve->curveData : NULL;
+}
+/* 10.2.11.2.7 CryptEccGetOID() */
+const BYTE *
+CryptEccGetOID(
+ TPM_ECC_CURVE curveId
+ )
+{
+ const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
+ return (curve != NULL) ? curve->OID : NULL;
+}
+/* 10.2.11.2.7 CryptEccGetCurveByIndex() */
+/* This function returns the number of the i-th implemented curve. The normal use would be to call
+ this function with i starting at 0. When the i is greater than or equal to the number of
+ implemented curves, TPM_ECC_NONE is returned. */
+LIB_EXPORT TPM_ECC_CURVE
+CryptEccGetCurveByIndex(
+ UINT16 i
+ )
+{
+ if(i >= ECC_CURVE_COUNT)
+ return TPM_ECC_NONE;
+ return eccCurves[i].curveId;
+}
+/* 10.2.11.2.8 CryptEccGetParameter() */
+/* This function returns an ECC curve parameter. The parameter is selected by a single character
+ designator from the set of {PNABXYH}. */
+/* Return Values Meaning */
+/* TRUE curve exists and parameter returned */
+/* FALSE curve does not exist or parameter selector */
+LIB_EXPORT BOOL
+CryptEccGetParameter(
+ TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter
+ char p, // IN: the parameter selector
+ TPM_ECC_CURVE curveId // IN: the curve id
+ )
+{
+ const ECC_CURVE_DATA *curve = GetCurveData(curveId);
+ bigConst parameter = NULL;
+ if(curve != NULL)
+ {
+ switch(p)
+ {
+ case 'p':
+ parameter = CurveGetPrime(curve);
+ break;
+ case 'n':
+ parameter = CurveGetOrder(curve);
+ break;
+ case 'a':
+ parameter = CurveGet_a(curve);
+ break;
+ case 'b':
+ parameter = CurveGet_b(curve);
+ break;
+ case 'x':
+ parameter = CurveGetGx(curve);
+ break;
+ case 'y':
+ parameter = CurveGetGy(curve);
+ break;
+ case 'h':
+ parameter = CurveGetCofactor(curve);
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ }
+ // If not debugging and we get here with parameter still NULL, had better
+ // not try to convert so just return FALSE instead.
+ return (parameter != NULL) ? BnTo2B(parameter, &out->b, 0) : 0;
+}
+/* 10.2.11.2.9 CryptCapGetECCCurve() */
+/* This function returns the list of implemented ECC curves. */
+/* Return Values Meaning */
+/* YES if no more ECC curve is available */
+/* NO if there are more ECC curves not reported */
+TPMI_YES_NO
+CryptCapGetECCCurve(
+ TPM_ECC_CURVE curveID, // IN: the starting ECC curve
+ UINT32 maxCount, // IN: count of returned curves
+ TPML_ECC_CURVE *curveList // OUT: ECC curve list
+ )
+{
+ TPMI_YES_NO more = NO;
+ UINT16 i;
+ UINT32 count = ECC_CURVE_COUNT;
+ TPM_ECC_CURVE curve;
+ // Initialize output property list
+ curveList->count = 0;
+ // The maximum count of curves we may return is MAX_ECC_CURVES
+ if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES;
+ // Scan the eccCurveValues array
+ for(i = 0; i < count; i++)
+ {
+ curve = CryptEccGetCurveByIndex(i);
+ // If curveID is less than the starting curveID, skip it
+ if(curve < curveID)
+ continue;
+ if (!CryptEccIsCurveRuntimeUsable(curve)) // libtpms added: runtime filter supported curves
+ continue;
+ if(curveList->count < maxCount)
+ {
+ // If we have not filled up the return list, add more curves to
+ // it
+ curveList->eccCurves[curveList->count] = curve;
+ curveList->count++;
+ }
+ else
+ {
+ // If the return list is full but we still have curves
+ // available, report this and stop iterating
+ more = YES;
+ break;
+ }
+ }
+ return more;
+}
+/* 10.2.11.2.10 CryptGetCurveSignScheme() */
+/* This function will return a pointer to the scheme of the curve. */
+const TPMT_ECC_SCHEME *
+CryptGetCurveSignScheme(
+ TPM_ECC_CURVE curveId // IN: The curve selector
+ )
+{
+ const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
+ if(curve != NULL)
+ return &(curve->sign);
+ else
+ return NULL;
+}
+/* 10.2.11.2.11 CryptGenerateR() */
+/* This function computes the commit random value for a split signing scheme. */
+/* If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM
+ will validate that the gr.commitArray bit associated with the input value of c is SET. If not,
+ the TPM returns FALSE and no r value is generated. */
+/* Return Values Meaning */
+/* TRUE r value computed */
+/* FALSE no r value computed */
+BOOL
+CryptGenerateR(
+ TPM2B_ECC_PARAMETER *r, // OUT: the generated random value
+ UINT16 *c, // IN/OUT: count value.
+ TPMI_ECC_CURVE curveID, // IN: the curve for the value
+ TPM2B_NAME *name // IN: optional name of a key to
+ // associate with 'r'
+ )
+{
+ // This holds the marshaled g_commitCounter.
+ TPM2B_TYPE(8B, 8);
+ TPM2B_8B cntr = {{8,{0}}};
+ UINT32 iterations;
+ TPM2B_ECC_PARAMETER n;
+ UINT64 currentCount = gr.commitCounter;
+ UINT16 t1;
+ //
+ if(!CryptEccGetParameter(&n, 'n', curveID))
+ return FALSE;
+ // If this is the commit phase, use the current value of the commit counter
+ if(c != NULL)
+ {
+ // if the array bit is not set, can't use the value.
+ if(!TEST_BIT((*c & COMMIT_INDEX_MASK), gr.commitArray))
+ return FALSE;
+ // If it is the sign phase, figure out what the counter value was
+ // when the commitment was made.
+ //
+ // When gr.commitArray has less than 64K bits, the extra
+ // bits of 'c' are used as a check to make sure that the
+ // signing operation is not using an out of range count value
+ t1 = (UINT16)currentCount;
+ // If the lower bits of c are greater or equal to the lower bits of t1
+ // then the upper bits of t1 must be one more than the upper bits
+ // of c
+ if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK))
+ // Since the counter is behind, reduce the current count
+ currentCount = currentCount - (COMMIT_INDEX_MASK + 1);
+ t1 = (UINT16)currentCount;
+ if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK))
+ return FALSE;
+ // set the counter to the value that was
+ // present when the commitment was made
+ currentCount = (currentCount & 0xffffffffffff0000ULL) | *c; /* libtpms changed */
+ }
+ // Marshal the count value to a TPM2B buffer for the KDF
+ cntr.t.size = sizeof(currentCount);
+ UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer);
+ // Now can do the KDF to create the random value for the signing operation
+ // During the creation process, we may generate an r that does not meet the
+ // requirements of the random value.
+ // want to generate a new r.
+ r->t.size = n.t.size;
+ for(iterations = 1; iterations < 1000000;)
+ {
+ int i;
+
+ CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gr.commitNonce.b, COMMIT_STRING,
+ (TPM2B *)name, &cntr.b, n.t.size * 8, // libtpms ubsan
+ r->t.buffer, &iterations, FALSE); // libtpms changed
+
+ // "random" value must be less than the prime
+ if(UnsignedCompareB(r->b.size, r->b.buffer, n.t.size, n.t.buffer) >= 0)
+ continue;
+
+ // in this implementation it is required that at least bit
+ // in the upper half of the number be set
+ for(i = n.t.size / 2; i >= 0; i--)
+ if(r->b.buffer[i] != 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+/* 10.2.11.2.12 CryptCommit() */
+/* This function is called when the count value is committed. The gr.commitArray value associated
+ with the current count value is SET and g_commitCounter is incremented. The low-order 16 bits of
+ old value of the counter is returned. */
+UINT16
+CryptCommit(
+ void
+ )
+{
+ UINT16 oldCount = (UINT16)gr.commitCounter;
+ gr.commitCounter++;
+ SET_BIT(oldCount & COMMIT_INDEX_MASK, gr.commitArray);
+ return oldCount;
+}
+/* 10.2.11.2.13 CryptEndCommit() */
+/* This function is called when the signing operation using the committed value is completed. It
+ clears the gr.commitArray bit associated with the count value so that it can't be used again. */
+void
+CryptEndCommit(
+ UINT16 c // IN: the counter value of the commitment
+ )
+{
+ ClearBit((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray));
+}
+/* 10.2.11.2.14 CryptEccGetParameters() */
+/* This function returns the ECC parameter details of the given curve */
+/* Return Values Meaning */
+/* TRUE success */
+/* FALSE unsupported ECC curve ID */
+BOOL
+CryptEccGetParameters(
+ TPM_ECC_CURVE curveId, // IN: ECC curve ID
+ TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters
+ )
+{
+ const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
+ const ECC_CURVE_DATA *data;
+ BOOL found = curve != NULL;
+ if(found)
+ {
+ data = curve->curveData;
+ parameters->curveID = curve->curveId;
+ parameters->keySize = curve->keySizeBits;
+ parameters->kdf = curve->kdf;
+ parameters->sign = curve->sign;
+ /* BnTo2B(data->prime, &parameters->p.b, 0); */
+ BnTo2B(data->prime, &parameters->p.b, parameters->p.t.size);
+ BnTo2B(data->a, &parameters->a.b, parameters->p.t.size /* libtpms changed for HLK */);
+ BnTo2B(data->b, &parameters->b.b, parameters->p.t.size /* libtpms changed for HLK */);
+ BnTo2B(data->base.x, &parameters->gX.b, parameters->p.t.size);
+ BnTo2B(data->base.y, &parameters->gY.b, parameters->p.t.size);
+ BnTo2B(data->order, &parameters->n.b, 0);
+ BnTo2B(data->h, &parameters->h.b, 0);
+ }
+ return found;
+}
+/* 10.2.11.2.15 BnGetCurvePrime() */
+/* This function is used to get just the prime modulus associated with a curve */
+const bignum_t *
+BnGetCurvePrime(
+ TPM_ECC_CURVE curveId
+ )
+{
+ const ECC_CURVE_DATA *C = GetCurveData(curveId);
+ return (C != NULL) ? CurveGetPrime(C) : NULL;
+}
+/* 10.2.11.2.16 BnGetCurveOrder() */
+/* This function is used to get just the curve order */
+const bignum_t *
+BnGetCurveOrder(
+ TPM_ECC_CURVE curveId
+ )
+{
+ const ECC_CURVE_DATA *C = GetCurveData(curveId);
+ return (C != NULL) ? CurveGetOrder(C) : NULL;
+}
+/* 10.2.11.2.17 BnIsOnCurve() */
+/* This function checks if a point is on the curve. */
+BOOL
+BnIsOnCurve(
+ pointConst Q,
+ const ECC_CURVE_DATA *C
+ )
+{
+ BN_VAR(right, (MAX_ECC_KEY_BITS * 3));
+ BN_VAR(left, (MAX_ECC_KEY_BITS * 2));
+ bigConst prime = CurveGetPrime(C);
+ //
+ // Show that point is on the curve y^2 = x^3 + ax + b;
+ // Or y^2 = x(x^2 + a) + b
+ // y^2
+ BnMult(left, Q->y, Q->y);
+ BnMod(left, prime);
+ // x^2
+ BnMult(right, Q->x, Q->x);
+ // x^2 + a
+ BnAdd(right, right, CurveGet_a(C));
+ // BnMod(right, CurveGetPrime(C));
+ // x(x^2 + a)
+ BnMult(right, right, Q->x);
+ // x(x^2 + a) + b
+ BnAdd(right, right, CurveGet_b(C));
+ BnMod(right, prime);
+ if(BnUnsignedCmp(left, right) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+/* 10.2.11.2.18 BnIsValidPrivateEcc() */
+/* Checks that 0 < x < q */
+BOOL
+BnIsValidPrivateEcc(
+ bigConst x, // IN: private key to check
+ bigCurve E // IN: the curve to check
+ )
+{
+ BOOL retVal;
+ retVal = (!BnEqualZero(x)
+ && (BnUnsignedCmp(x, CurveGetOrder(AccessCurveData(E))) < 0));
+ return retVal;
+}
+LIB_EXPORT BOOL
+CryptEccIsValidPrivateKey(
+ TPM2B_ECC_PARAMETER *d,
+ TPM_ECC_CURVE curveId
+ )
+{
+ BN_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d);
+ return !BnEqualZero(bnD) && (BnUnsignedCmp(bnD, BnGetCurveOrder(curveId)) < 0);
+}
+/* 10.2.11.2.19 BnPointMul() */
+/* This function does a point multiply of the form R = [d]S + [u]Q where the parameters are bigNum
+ values. If S is NULL and d is not NULL, then it computes R = [d]G + [u]Q or just R = [d]G if u
+ and Q are NULL. If skipChecks is TRUE, then the function will not verify that the inputs are
+ correct for the domain. This would be the case when the values were created by the CryptoEngine()
+ code. It will return TPM_RC_NO_RESULT if the resulting point is the point at infinity. */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT result of multiplication is a point at infinity */
+/* TPM_RC_ECC_POINT S or Q is not on the curve */
+/* TPM_RC_VALUE d or u is not < n */
+TPM_RC
+BnPointMult(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: optional point to multiply by 'd'
+ bigConst d, // IN: scalar for [d]S or [d]G
+ pointConst Q, // IN: optional second point
+ bigConst u, // IN: optional second scalar
+ bigCurve E // IN: curve parameters
+ )
+{
+ BOOL OK;
+ //
+ TEST(TPM_ALG_ECDH);
+ // Need one scalar
+ OK = (d != NULL || u != NULL);
+ // If S is present, then d has to be present. If S is not
+ // present, then d may or may not be present
+ OK = OK && (((S == NULL) == (d == NULL)) || (d != NULL));
+ // either both u and Q have to be provided or neither can be provided (don't
+ // know what to do if only one is provided.
+ OK = OK && ((u == NULL) == (Q == NULL));
+ OK = OK && (E != NULL);
+ if(!OK)
+ return TPM_RC_VALUE;
+ OK = (S == NULL) || BnIsOnCurve(S, AccessCurveData(E));
+ OK = OK && ((Q == NULL) || BnIsOnCurve(Q, AccessCurveData(E)));
+ if(!OK)
+ return TPM_RC_ECC_POINT;
+ if((d != NULL) && (S == NULL))
+ S = CurveGetG(AccessCurveData(E));
+ // If only one scalar, don't need Shamir's trick
+ if((d == NULL) || (u == NULL))
+ {
+ if(d == NULL)
+ OK = BnEccModMult(R, Q, u, E);
+ else
+ OK = BnEccModMult(R, S, d, E);
+ }
+ else
+ {
+ OK = BnEccModMult2(R, S, d, Q, u, E);
+ }
+ return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT);
+}
+/* 10.2.11.2.20 BnEccGetPrivate() */
+/* This function gets random values that are the size of the key plus 64 bits. The value is reduced
+ (mod (q - 1)) and incremented by 1 (q is the order of the curve. This produces a value (d) such
+ that 1 <= d < q. This is the method of FIPS 186-4 Section B.4.1 'Key Pair Generation Using Extra
+ Random Value Meaning */
+/* TRUE success */
+/* FALSE failure generating private key */
+#if !USE_OPENSSL_FUNCTIONS_EC // libtpms added
+BOOL
+BnEccGetPrivate(
+ bigNum dOut, // OUT: the qualified random value
+ const ECC_CURVE_DATA *C, // IN: curve for which the private key
+ // needs to be appropriate
+ RAND_STATE *rand // IN: state for DRBG
+ )
+{
+ bigConst order = CurveGetOrder(C);
+ BOOL OK;
+ UINT32 orderBits = BnSizeInBits(order);
+ UINT32 orderBytes = BITS_TO_BYTES(orderBits);
+ BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
+ BN_VAR(nMinus1, MAX_ECC_KEY_BITS);
+ //
+ OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand);
+ OK = OK && BnSubWord(nMinus1, order, 1);
+ OK = OK && BnMod(bnExtraBits, nMinus1);
+ OK = OK && BnAddWord(dOut, bnExtraBits, 1);
+ return OK && !g_inFailureMode;
+}
+#else // libtpms added begin
+BOOL
+BnEccGetPrivate(
+ 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
+ )
+{
+ bigConst order = CurveGetOrder(C);
+ 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) {
+ if (noLeadingZeros)
+ requestedBits = orderBits;
+
+ return OpenSSLEccGetPrivate(dOut, G, requestedBits);
+ }
+
+ //
+ OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand);
+ OK = OK && BnSubWord(nMinus1, order, 1);
+ OK = OK && BnMod(bnExtraBits, nMinus1);
+ OK = OK && BnAddWord(dOut, bnExtraBits, 1);
+ return OK && !g_inFailureMode;
+}
+#endif // USE_OPENSSL_FUNCTIONS_EC libtpms added end
+/* 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
+ 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;
+ // Get a private scalar
+ OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand);
+ // Do a point multiply
+ OK = OK && BnEccModMult(ecQ, NULL, bnD, E);
+ if(!OK)
+ BnSetWord(ecQ->z, 0);
+ else
+ 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.11.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 */
+LIB_EXPORT TPM_RC
+CryptEccNewKeyPair(
+ TPMS_ECC_POINT *Qout, // OUT: the public point
+ TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar
+ TPM_ECC_CURVE curveId // IN: the curve for the key
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ POINT(ecQ);
+ ECC_NUM(bnD);
+ BOOL OK;
+ if(E == NULL)
+ return TPM_RC_CURVE;
+ TEST(TPM_ALG_ECDH);
+ OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL);
+ if(OK)
+ {
+ BnPointTo2B(Qout, ecQ, E);
+ BnTo2B(bnD, &dOut->b, Qout->x.t.size);
+ }
+ else
+ {
+ Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0;
+ }
+ CURVE_FREE(E);
+ return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
+}
+/* 10.2.11.2.22 CryptEccPointMultiply() */
+/* This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are
+ points on the specified curve and G is the default generator of the curve. */
+/* The xOut and yOut parameters are optional and may be set to NULL if not used. */
+/* It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be
+ provided. If dIn and QIn are specified but uIn is not provided, then R = [dIn]QIn. */
+/* If the multiply produces the point at infinity, the TPM_RC_NO_RESULT is returned. */
+/* The sizes of xOut and yOut' will be set to be the size of the degree of the curve */
+/* It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is
+ unspecified. */
+/* Error Returns Meaning */
+/* TPM_RC_ECC_POINT the point Pin or Qin is not on the curve */
+/* TPM_RC_NO_RESULT the product point is at infinity */
+/* TPM_RC_CURVE bad curve */
+/* TPM_RC_VALUE dIn or uIn out of range */
+LIB_EXPORT TPM_RC
+CryptEccPointMultiply(
+ TPMS_ECC_POINT *Rout, // OUT: the product point R
+ TPM_ECC_CURVE curveId, // IN: the curve to use
+ TPMS_ECC_POINT *Pin, // IN: first point (can be null)
+ TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin
+ // the Pin
+ TPMS_ECC_POINT *Qin, // IN: point Q
+ TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier
+ // of Q
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ POINT_INITIALIZED(ecP, Pin);
+ ECC_INITIALIZED(bnD, dIn); // If dIn is null, then bnD is null
+ ECC_INITIALIZED(bnU, uIn);
+ POINT_INITIALIZED(ecQ, Qin);
+ POINT(ecR);
+ TPM_RC retVal;
+ //
+ retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E);
+ if(retVal == TPM_RC_SUCCESS)
+ BnPointTo2B(Rout, ecR, E);
+ else
+ ClearPoint2B(Rout);
+ CURVE_FREE(E);
+ return retVal;
+}
+/* 10.2.11.2.23 CryptEccIsPointOnCurve() */
+/* This function is used to test if a point is on a defined curve. It does this by checking that y^2
+ mod p = x^3 + a*x + b mod p */
+/* It is a fatal error if Q is not specified (is NULL). */
+/* Return Values Meaning */
+/* TRUE point is on curve */
+/* FALSE point is not on curve or curve is not supported */
+LIB_EXPORT BOOL
+CryptEccIsPointOnCurve(
+ TPM_ECC_CURVE curveId, // IN: the curve selector
+ TPMS_ECC_POINT *Qin // IN: the point.
+ )
+{
+ const ECC_CURVE_DATA *C = GetCurveData(curveId);
+ POINT_INITIALIZED(ecQ, Qin);
+ BOOL OK;
+ //
+ pAssert(Qin != NULL);
+ OK = (C != NULL && (BnIsOnCurve(ecQ, C)));
+ return OK;
+}
+/* 10.2.11.2.24 CryptEccGenerateKey() */
+/* This function generates an ECC key pair based on the input parameters. This routine uses KDFa()
+ to produce candidate numbers. The method is according to FIPS 186-3, section B.1.2 "Key Pair
+ Generation by Testing Candidates." According to the method in FIPS 186-3, the resulting private
+ value d should be 1 <= d < n where n is the order of the base point. */
+/* It is a fatal error if Qout, dOut, is not provided (is NULL). */
+/* If the curve is not supported If seed is not provided, then a random number will be used for the
+ key */
+/* Error Returns Meaning */
+/* TPM_RC_CURVE curve is not supported */
+/* TPM_RC_NO_RESULT could not verify key with signature (FIPS only) */
+LIB_EXPORT TPM_RC
+CryptEccGenerateKey(
+ TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for
+ // the new key. The public key
+ // area will be replaced computed
+ // ECC public key
+ TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be
+ // updated to contain the private
+ // ECC key and the symmetric
+ // encryption key
+ RAND_STATE *rand // IN: if not NULL, the deterministic
+ // RNG state
+ )
+{
+ CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID);
+ ECC_NUM(bnD);
+ POINT(ecQ);
+ BOOL OK;
+ TPM_RC retVal;
+ TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key
+ // Validate parameters
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_CURVE);
+ publicArea->unique.ecc.x.t.size = 0;
+ publicArea->unique.ecc.y.t.size = 0;
+ sensitive->sensitive.ecc.t.size = 0;
+ OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand);
+ if(OK)
+ {
+ BnPointTo2B(&publicArea->unique.ecc, ecQ, E);
+ BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size);
+ }
+#if FIPS_COMPLIANT
+ // See if PWCT is required
+ if(OK && (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)))
+ {
+ ECC_NUM(bnT);
+ ECC_NUM(bnS);
+ TPM2B_DIGEST digest;
+ TEST(TPM_ALG_ECDSA);
+ digest.t.size = MIN(sensitive->sensitive.ecc.t.size, sizeof(digest.t.buffer));
+ // Get a random value to sign using the built in DRBG state
+ DRBG_Generate(NULL, digest.t.buffer, digest.t.size);
+ if(g_inFailureMode)
+ return TPM_RC_FAILURE;
+ BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL);
+ // and make sure that we can validate the signature
+ OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS;
+ }
+#endif
+ retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+
+// libtpms added begin
+// Support for some curves may be compiled in but they may not be
+// supported by openssl's crypto library.
+LIB_EXPORT BOOL
+CryptEccIsCurveRuntimeUsable(
+ TPMI_ECC_CURVE curveId
+ )
+{
+ CURVE_INITIALIZED(E, curveId);
+ if (E == NULL)
+ return FALSE;
+ CURVE_FREE(E);
+ return TRUE;
+}
+// libtpms added end
+
+#endif // TPM_ALG_ECC
diff --git a/src/tpm2/crypto/openssl/CryptEccSignature.c b/src/tpm2/crypto/openssl/CryptEccSignature.c
new file mode 100644
index 0000000..a325a46
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptEccSignature.c
@@ -0,0 +1,1043 @@
+/********************************************************************************/
+/* */
+/* ECC Signatures */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptEccSignature.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.12 CryptEccSignature.c */
+/* 10.2.12.1 Includes and Defines */
+#include "Tpm.h"
+#include "CryptEccSignature_fp.h"
+#include "TpmToOsslMath_fp.h" // libtpms added
+#if ALG_ECC
+/* 10.2.12.2 Utility Functions */
+/* 10.2.12.2.1 EcdsaDigest() */
+/* Function to adjust the digest so that it is no larger than the order of the curve. This is used
+ for ECDSA sign and verification. */
+#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added
+static bigNum
+EcdsaDigest(
+ bigNum bnD, // OUT: the adjusted digest
+ const TPM2B_DIGEST *digest, // IN: digest to adjust
+ bigConst max // IN: value that indicates the maximum
+ // number of bits in the results
+ )
+{
+ int bitsInMax = BnSizeInBits(max);
+ int shift;
+ //
+ if(digest == NULL)
+ BnSetWord(bnD, 0);
+ else
+ {
+ BnFromBytes(bnD, digest->t.buffer,
+ (NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax)));
+ shift = BnSizeInBits(bnD) - bitsInMax;
+ if(shift > 0)
+ BnShiftRight(bnD, bnD, shift);
+ }
+ return bnD;
+}
+#endif // libtpms added
+/* 10.2.12.2.2 BnSchnorrSign() */
+/* This contains the Schnorr signature computation. It is used by both ECDSA and Schnorr
+ signing. The result is computed as: [s = k + r * d (mod n)] where */
+/* a) s is the signature */
+/* b) k is a random value */
+/* c) r is the value to sign */
+/* d) d is the private EC key */
+/* e) n is the order of the curve */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT the result of the operation was zero or r (mod n) is zero */
+static TPM_RC
+BnSchnorrSign(
+ bigNum bnS, // OUT: s component of the signature
+ bigConst bnK, // IN: a random value
+ bigNum bnR, // IN: the signature 'r' value
+ bigConst bnD, // IN: the private key
+ bigConst bnN // IN: the order of the curve
+ )
+{
+ // Need a local temp value to store the intermediate computation because product
+ // size can be larger than will fit in bnS.
+ BN_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8);
+ //
+ // Reduce bnR without changing the input value
+ BnDiv(NULL, bnT1, bnR, bnN);
+ if(BnEqualZero(bnT1))
+ return TPM_RC_NO_RESULT;
+ // compute s = (k + r * d)(mod n)
+ // r * d
+ BnMult(bnT1, bnT1, bnD);
+ // k * r * d
+ BnAdd(bnT1, bnT1, bnK);
+ // k + r * d (mod n)
+ BnDiv(NULL, bnS, bnT1, bnN);
+ return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS;
+}
+/* 10.2.12.3 Signing Functions */
+/* 10.2.12.3.1 BnSignEcdsa() */
+/* This function implements the ECDSA signing algorithm. The method is described in the comments
+ below. This version works with internal numbers. */
+#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added
+TPM_RC
+BnSignEcdsa(
+ bigNum bnR, // OUT: r component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bigNum bnD, // IN: private signing key
+ const TPM2B_DIGEST *digest, // IN: the digest to sign
+ RAND_STATE *rand // IN: used in debug of signing
+ )
+{
+ ECC_NUM(bnK);
+ ECC_NUM(bnIk);
+ BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8);
+ POINT(ecR);
+ bigConst order = CurveGetOrder(AccessCurveData(E));
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ INT32 tries = 10;
+ BOOL OK = FALSE;
+ //
+ pAssert(digest != NULL);
+ // The algorithm as described in "Suite B Implementer's Guide to FIPS
+ // 186-3(ECDSA)"
+ // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a
+ // per-message secret number and its inverse modulo n. Since n is prime,
+ // the output will be invalid only if there is a failure in the RBG.
+ // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar
+ // multiplication (see [Routines]), where G is the base point included in
+ // the set of domain parameters.
+ // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1.
+ // 4. Use the selected hash function to compute H = Hash(M).
+ // 5. Convert the bit string H to an integer e as described in Appendix B.2.
+ // 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2.
+ // 7. Return (r, s).
+ // In the code below, q is n (that it, the order of the curve is p)
+ do // This implements the loop at step 6. If s is zero, start over.
+ {
+ for(; tries > 0; tries--)
+ {
+ // Step 1 and 2 -- generate an ephemeral key and the modular inverse
+ // of the private key.
+ if(!BnEccGenerateKeyPair(bnK, ecR, E, rand))
+ continue;
+ // x coordinate is mod p. Make it mod q
+ BnMod(ecR->x, order);
+ // Make sure that it is not zero;
+ if(BnEqualZero(ecR->x))
+ continue;
+ // write the modular reduced version of r as part of the signature
+ BnCopy(bnR, ecR->x);
+ // Make sure that a modular inverse exists and try again if not
+ OK = (BnModInverse(bnIk, bnK, order));
+ if(OK)
+ break;
+ }
+ if(!OK)
+ goto Exit;
+ EcdsaDigest(bnE, digest, order);
+ // now have inverse of K (bnIk), e (bnE), r (bnR), d (bnD) and
+ // CurveGetOrder(E)
+ // Compute s = k^-1 (e + r*d)(mod q)
+ // first do s = r*d mod q
+ BnModMult(bnS, bnR, bnD, order);
+ // s = e + s = e + r * d
+ BnAdd(bnS, bnE, bnS);
+ // s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n)
+ BnModMult(bnS, bnIk, bnS, order);
+ // If S is zero, try again
+ } while(BnEqualZero(bnS));
+ Exit:
+ return retVal;
+}
+#else // !USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin
+TPM_RC
+BnSignEcdsa(
+ bigNum bnR, // OUT: r component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bigNum bnD, // IN: private signing key
+ const TPM2B_DIGEST *digest, // IN: the digest to sign
+ RAND_STATE *rand // IN: used in debug of signing
+ )
+{
+ ECDSA_SIG *sig = NULL;
+ EC_KEY *eckey;
+ int retVal;
+ const BIGNUM *r;
+ const BIGNUM *s;
+ BIGNUM *d = BN_new();
+
+ d = BigInitialized(d, bnD);
+
+ eckey = EC_KEY_new();
+
+ if (d == NULL || eckey == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EC_KEY_set_group(eckey, E->G) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EC_KEY_set_private_key(eckey, d) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ sig = ECDSA_do_sign(digest->b.buffer, digest->b.size, eckey);
+ if (sig == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ ECDSA_SIG_get0(sig, &r, &s);
+ OsslToTpmBn(bnR, r);
+ OsslToTpmBn(bnS, s);
+
+ retVal = TPM_RC_SUCCESS;
+
+ Exit:
+ BN_clear_free(d);
+ EC_KEY_free(eckey);
+ ECDSA_SIG_free(sig);
+
+ return retVal;
+}
+#endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end
+#if ALG_ECDAA
+/* 10.2.12.3.2 BnSignEcdaa() */
+/* This function performs s = r + T * d mod q where */
+/* a) 'r is a random, or pseudo-random value created in the commit phase */
+/* b) nonceK is a TPM-generated, random value 0 < nonceK < n */
+/* c) T is mod q of Hash(nonceK || digest), and */
+/* d) d is a private key. */
+/* The signature is the tuple (nonceK, s) */
+/* Regrettably, the parameters in this function kind of collide with the parameter names used in
+ ECSCHNORR making for a lot of confusion. In particular, the k value in this function is value in
+ this function u */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME unsupported hash algorithm */
+/* TPM_RC_NO_RESULT cannot get values from random number generator */
+static TPM_RC
+BnSignEcdaa(
+ TPM2B_ECC_PARAMETER *nonceK, // OUT: nonce component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in signing
+ bigNum bnD, // IN: the private key
+ const TPM2B_DIGEST *digest, // IN: the value to sign (mod q)
+ TPMT_ECC_SCHEME *scheme, // IN: signing scheme (contains the
+ // commit count value).
+ OBJECT *eccKey, // IN: The signing key
+ RAND_STATE *rand // IN: a random number state
+ )
+{
+ TPM_RC retVal;
+ TPM2B_ECC_PARAMETER r;
+ HASH_STATE state;
+ TPM2B_DIGEST T;
+ BN_MAX(bnT);
+ //
+ NOT_REFERENCED(rand);
+ if(!CryptGenerateR(&r, &scheme->details.ecdaa.count,
+ eccKey->publicArea.parameters.eccDetail.curveID,
+ &eccKey->name))
+ retVal = TPM_RC_VALUE;
+ else
+ {
+ // This allocation is here because 'r' doesn't have a value until
+ // CrypGenerateR() is done.
+ ECC_INITIALIZED(bnR, &r);
+ do
+ {
+ // 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, false, rand))
+#else // libtpms added end
+ if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand))
+#endif // libtpms added
+ {
+ retVal = TPM_RC_NO_RESULT;
+ break;
+ }
+ BnTo2B(bnT, &nonceK->b, 0);
+ T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg);
+ if(T.t.size == 0)
+ {
+ retVal = TPM_RC_SCHEME;
+ }
+ else
+ {
+ CryptDigestUpdate2B(&state, &nonceK->b);
+ 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);
+ }
+ } while(retVal == TPM_RC_NO_RESULT);
+ // Because the rule is that internal state is not modified if the command
+ // fails, only end the commit if the command succeeds.
+ // NOTE that if the result of the Schnorr computation was zero
+ // it will probably not be worthwhile to run the same command again because
+ // the result will still be zero. This means that the Commit command will
+ // need to be run again to get a new commit value for the signature.
+ if(retVal == TPM_RC_SUCCESS)
+ CryptEndCommit(scheme->details.ecdaa.count);
+ }
+ return retVal;
+}
+#endif // ALG_ECDAA
+#if ALG_ECSCHNORR
+/* 10.2.12.3.3 SchnorrReduce() */
+/* Function to reduce a hash result if it's magnitude is to large. The size of number is set so that
+ it has no more bytes of significance than the reference value. If the resulting number can have
+ more bits of significance than the reference. */
+static void
+SchnorrReduce(
+ TPM2B *number, // IN/OUT: Value to reduce
+ bigConst reference // IN: the reference value
+ )
+{
+ UINT16 maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference));
+ if(number->size > maxBytes)
+ number->size = maxBytes;
+}
+/* 10.2.12.3.4 SchnorrEcc() */
+/* This function is used to perform a modified Schnorr signature. */
+/* This function will generate a random value k and compute */
+/* a) (xR, yR) = [k]G */
+/* b) r = hash(xR || P)(mod q) */
+/* c) rT = truncated r */
+/* d) s= k + rT * ds (mod q) */
+/* e) return the tuple rT, s */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT failure in the Schnorr sign process */
+/* TPM_RC_SCHEME hashAlg can't produce zero-length digest */
+static TPM_RC
+BnSignEcSchnorr(
+ bigNum bnR, // OUT: r component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in signing
+ bigNum bnD, // IN: the signing key
+ const TPM2B_DIGEST *digest, // IN: the digest to sign
+ TPM_ALG_ID hashAlg, // IN: signing scheme (contains a hash)
+ RAND_STATE *rand // IN: non-NULL when testing
+ )
+{
+ HASH_STATE hashState;
+ UINT16 digestSize
+ = CryptHashGetDigestSize(hashAlg);
+ TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES));
+ TPM2B_T T2b;
+ TPM2B *e = &T2b.b;
+ TPM_RC retVal = TPM_RC_NO_RESULT;
+ const ECC_CURVE_DATA *C;
+ bigConst order;
+ bigConst prime;
+ ECC_NUM(bnK);
+ POINT(ecR);
+ //
+ // Parameter checks
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+ C = AccessCurveData(E);
+ order = CurveGetOrder(C);
+ prime = CurveGetOrder(C);
+ // If the digest does not produce a hash, then null the signature and return
+ // a failure.
+ if(digestSize == 0)
+ {
+ BnSetWord(bnR, 0);
+ BnSetWord(bnS, 0);
+ ERROR_RETURN(TPM_RC_SCHEME);
+ }
+ do
+ {
+ // Generate a random key pair
+ if(!BnEccGenerateKeyPair(bnK, ecR, E, rand))
+ break;
+ // Convert R.x to a string
+ BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime)));
+ // f) compute r = Hash(e || P) (mod n)
+ CryptHashStart(&hashState, hashAlg);
+ CryptDigestUpdate2B(&hashState, e);
+ CryptDigestUpdate2B(&hashState, &digest->b);
+ e->size = CryptHashEnd(&hashState, digestSize, e->buffer);
+ // Reduce the hash size if it is larger than the curve order
+ 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);
+ Exit:
+ return retVal;
+}
+#endif // ALG_ECSCHNORR
+#if ALG_SM2
+#ifdef _SM2_SIGN_DEBUG
+/* 10.2.12.3.5 BnHexEqual() */
+/* This function compares a bignum value to a hex string. */
+/* Return Value Meaning */
+/* TRUE(1) values equal */
+/* FALSE(0) values not equal */
+static BOOL
+BnHexEqual(
+ bigNum bn, //IN: big number value
+ const char *c //IN: character string number
+ )
+{
+ ECC_NUM(bnC);
+ BnFromHex(bnC, c);
+ return (BnUnsignedCmp(bn, bnC) == 0);
+}
+#endif // _SM2_SIGN_DEBUG
+/* 10.2.12.3.5 BnSignEcSm2() */
+/* This function signs a digest using the method defined in SM2 Part 2. The method in the standard
+ will add a header to the message to be signed that is a hash of the values that define the
+ key. This then hashed with the message to produce a digest (e) that is signed. This function
+ signs e. */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE bad curve */
+static TPM_RC
+BnSignEcSm2(
+ bigNum bnR, // OUT: r component of the signature
+ bigNum bnS, // OUT: s component of the signature
+ bigCurve E, // IN: the curve used in signing
+ bigNum bnD, // IN: the private key
+ const TPM2B_DIGEST *digest, // IN: the digest to sign
+ RAND_STATE *rand // IN: random number generator (mostly for
+ // debug)
+ )
+{
+ BN_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be
+ ECC_NUM(bnN);
+ ECC_NUM(bnK);
+ ECC_NUM(bnT); // temp
+ 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"
+ "9A87E6FC682D48BB5D42E3D9B9EFFE76");
+ BnFromHex(bnD, "128B2FA8BD433C6C068C8D803DFF7979"
+ "2A519A55171B1B650C23661D15897263");
+#endif
+ // A3: Use random number generator to generate random number 1 <= k <= n-1;
+ // NOTE: Ax: numbers are from the SM2 standard
+ loop:
+ {
+ // Get a random number 0 < k < n
+ // 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(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, 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);
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41"
+ "94F79FB1EED2CAA55BACDB49C4E755D1"));
+#endif
+ // if r=0 or r+k=n, return to A3;
+ if(BnEqualZero(bnR))
+ goto loop;
+ BnAdd(bnT, bnK, bnR);
+ if(BnUnsignedCmp(bnT, bnN) == 0)
+ goto loop;
+ // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n,
+ // if s=0, return to A3;
+ // compute t = (1+dA)^-1
+ BnAddWord(bnT, bnD, 1);
+ BnModInverse(bnT, bnT, order);
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(BnHexEqual(bnT, "79BFCF3052C80DA7B939E0C6914A18CB"
+ "B2D96D8555256E83122743A7D4F5F956"));
+#endif
+ // compute s = t * (k - r * dA) mod n
+ BnModMult(bnS, bnR, bnD, order);
+ // k - r * dA mod n = k + n - ((r * dA) mod n)
+ BnSub(bnS, order, bnS);
+ BnAdd(bnS, bnK, bnS);
+ BnModMult(bnS, bnS, bnT, order);
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6"
+ "67A457872FB09EC56327A67EC7DEEBE7"));
+#endif
+ if(BnEqualZero(bnS))
+ goto loop;
+ }
+ // A7: According to details specified in 4.2.1 in Part 1 of this document,
+ // transform the data type of r, s into bit strings, signature of message M
+ // is (r, s).
+ // This is handled by the common return code
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41"
+ "94F79FB1EED2CAA55BACDB49C4E755D1"));
+ pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6"
+ "67A457872FB09EC56327A67EC7DEEBE7"));
+#endif
+ return TPM_RC_SUCCESS;
+}
+#endif // ALG_SM2
+/* 10.2.12.3.6 CryptEccSign() */
+/* This function is the dispatch function for the various ECC-based signing schemes. There is a bit
+ of ugliness to the parameter passing. In order to test this, we sometime would like to use a
+ deterministic RNG so that we can get the same signatures during testing. The easiest way to do
+ this for most schemes is to pass in a deterministic RNG and let it return canned values during
+ testing. There is a competing need for a canned parameter to use in ECDAA. To accommodate both
+ needs with minimal fuss, a special type of RAND_STATE is defined to carry the address of the
+ commit value. The setup and handling of this is not very different for the caller than what was
+ in previous versions of the code. */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME scheme is not supported */
+LIB_EXPORT TPM_RC
+CryptEccSign(
+ TPMT_SIGNATURE *signature, // OUT: signature
+ OBJECT *signKey, // IN: ECC key to sign the hash
+ const TPM2B_DIGEST *digest, // IN: digest to sign
+ TPMT_ECC_SCHEME *scheme, // IN: signing scheme
+ RAND_STATE *rand
+ )
+{
+ CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
+ ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b);
+ ECC_NUM(bnR);
+ ECC_NUM(bnS);
+ const ECC_CURVE_DATA *C;
+ TPM_RC retVal = TPM_RC_SCHEME;
+ //
+ NOT_REFERENCED(scheme);
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+ C = AccessCurveData(E);
+ signature->signature.ecdaa.signatureR.t.size
+ = sizeof(signature->signature.ecdaa.signatureR.t.buffer);
+ signature->signature.ecdaa.signatureS.t.size
+ = sizeof(signature->signature.ecdaa.signatureS.t.buffer);
+ TEST(signature->sigAlg);
+ switch(signature->sigAlg)
+ {
+ case TPM_ALG_ECDSA:
+ retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand);
+ break;
+#if ALG_ECDAA
+ case TPM_ALG_ECDAA:
+ retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E,
+ bnD, digest, scheme, signKey, rand);
+ bnR = NULL;
+ break;
+#endif
+#if ALG_ECSCHNORR
+ case TPM_ALG_ECSCHNORR:
+ retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest,
+ signature->signature.ecschnorr.hash,
+ rand);
+ break;
+#endif
+#if ALG_SM2
+ case TPM_ALG_SM2:
+ retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand);
+ break;
+#endif
+ default:
+ break;
+ }
+ // If signature generation worked, convert the results.
+ if(retVal == TPM_RC_SUCCESS)
+ {
+ NUMBYTES orderBytes =
+ (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C)));
+ if(bnR != NULL)
+ BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes);
+ if(bnS != NULL)
+ BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes);
+ }
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+#if ALG_ECDSA
+/* 10.2.12.3.7 BnValidateSignatureEcdsa() */
+/* This function validates an ECDSA signature. rIn and sIn should have been checked to make sure
+ that they are in the range 0 < v < n */
+/* Error Returns Meaning */
+/* TPM_RC_SIGNATURE signature not valid */
+#if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added
+TPM_RC
+BnValidateSignatureEcdsa(
+ bigNum bnR, // IN: r component of the signature
+ bigNum bnS, // IN: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bn_point_t *ecQ, // IN: the public point of the key
+ const TPM2B_DIGEST *digest // IN: the digest that was signed
+ )
+{
+ // Make sure that the allocation for the digest is big enough for a maximum
+ // digest
+ BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8);
+ POINT(ecR);
+ ECC_NUM(bnU1);
+ ECC_NUM(bnU2);
+ ECC_NUM(bnW);
+ bigConst order = CurveGetOrder(AccessCurveData(E));
+ TPM_RC retVal = TPM_RC_SIGNATURE;
+ // Get adjusted digest
+ EcdsaDigest(bnE, digest, order);
+ // 1. If r and s are not both integers in the interval [1, n - 1], output
+ // INVALID.
+ // bnR and bnS were validated by the caller
+ // 2. Use the selected hash function to compute H0 = Hash(M0).
+ // This is an input parameter
+ // 3. Convert the bit string H0 to an integer e as described in Appendix B.2.
+ // Done at entry
+ // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1.
+ if(!BnModInverse(bnW, bnS, order))
+ goto Exit;
+ // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n.
+ BnModMult(bnU1, bnE, bnW, order);
+ BnModMult(bnU2, bnR, bnW, order);
+ // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC
+ // scalar multiplication and EC addition (see [Routines]). If R is equal to
+ // the point at infinity O, output INVALID.
+ if(BnPointMult(ecR, CurveGetG(AccessCurveData(E)), bnU1, ecQ, bnU2, E)
+ != TPM_RC_SUCCESS)
+ goto Exit;
+ // 7. Compute v = Rx mod n.
+ BnMod(ecR->x, order);
+ // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID
+ if(BnUnsignedCmp(ecR->x, bnR) != 0)
+ goto Exit;
+ retVal = TPM_RC_SUCCESS;
+ Exit:
+ return retVal;
+}
+#else // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin
+TPM_RC
+BnValidateSignatureEcdsa(
+ bigNum bnR, // IN: r component of the signature
+ bigNum bnS, // IN: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bn_point_t *ecQ, // IN: the public point of the key
+ const TPM2B_DIGEST *digest // IN: the digest that was signed
+ )
+{
+ int retVal;
+ int rc;
+ ECDSA_SIG *sig = NULL;
+ EC_KEY *eckey = NULL;
+ BIGNUM *r = BN_new();
+ BIGNUM *s = BN_new();
+ EC_POINT *q = EcPointInitialized(ecQ, E);
+
+ r = BigInitialized(r, bnR);
+ s = BigInitialized(s, bnS);
+
+ sig = ECDSA_SIG_new();
+ eckey = EC_KEY_new();
+
+ if (r == NULL || s == NULL || q == NULL || sig == NULL || eckey == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EC_KEY_set_group(eckey, E->G) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EC_KEY_set_public_key(eckey, q) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (ECDSA_SIG_set0(sig, r, s) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ /* sig now owns r and s */
+ r = NULL;
+ s = NULL;
+
+ rc = ECDSA_do_verify(digest->b.buffer, digest->b.size, sig, eckey);
+ switch (rc) {
+ case 1:
+ retVal = TPM_RC_SUCCESS;
+ break;
+ case 0:
+ retVal = TPM_RC_SIGNATURE;
+ break;
+ default:
+ retVal = TPM_RC_FAILURE;
+ break;
+ }
+
+ Exit:
+ EC_KEY_free(eckey);
+ ECDSA_SIG_free(sig);
+ EC_POINT_clear_free(q);
+ BN_clear_free(r);
+ BN_clear_free(s);
+
+ return retVal;
+}
+#endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end
+#endif // ALG_ECDSA
+#if ALG_SM2
+/* 10.2.12.3.8 BnValidateSignatureEcSm2() */
+/* This function is used to validate an SM2 signature. */
+/* Error Returns Meaning */
+/* TPM_RC_SIGNATURE signature not valid */
+static TPM_RC
+BnValidateSignatureEcSm2(
+ bigNum bnR, // IN: r component of the signature
+ bigNum bnS, // IN: s component of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bigPoint ecQ, // IN: the public point of the key
+ const TPM2B_DIGEST *digest // IN: the digest that was signed
+ )
+{
+ POINT(P);
+ ECC_NUM(bnRp);
+ ECC_NUM(bnT);
+ BN_MAX_INITIALIZED(bnE, digest);
+ BOOL OK;
+ bigConst order = CurveGetOrder(AccessCurveData(E));
+#ifdef _SM2_SIGN_DEBUG
+ // Make sure that the input signature is the test signature
+ pAssert(BnHexEqual(bnR,
+ "40F1EC59F793D9F49E09DCEF49130D41"
+ "94F79FB1EED2CAA55BACDB49C4E755D1"));
+ pAssert(BnHexEqual(bnS,
+ "6FC6DAC32C5D5CF10C77DFB20F7C2EB6"
+ "67A457872FB09EC56327A67EC7DEEBE7"));
+#endif
+ // b) compute t := (r + s) mod n
+ BnAdd(bnT, bnR, bnS);
+ BnMod(bnT, order);
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(BnHexEqual(bnT,
+ "2B75F07ED7ECE7CCC1C8986B991F441A"
+ "D324D6D619FE06DD63ED32E0C997C801"));
+#endif
+ // c) verify that t > 0
+ OK = !BnEqualZero(bnT);
+ if(!OK)
+ // set T to a value that should allow rest of the computations to run
+ // without trouble
+ BnCopy(bnT, bnS);
+ // d) compute (x, y) := [s]G + [t]Q
+ OK = BnEccModMult2(P, NULL, bnS, ecQ, bnT, E);
+#ifdef _SM2_SIGN_DEBUG
+ pAssert(OK && BnHexEqual(P->x,
+ "110FCDA57615705D5E7B9324AC4B856D"
+ "23E6D9188B2AE47759514657CE25D112"));
+#endif
+ // e) compute r' := (e + x) mod n (the x coordinate is in bnT)
+ OK = OK && BnAdd(bnRp, bnE, P->x);
+ OK = OK && BnMod(bnRp, order);
+ // f) verify that r' = r
+ OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0);
+
+ if(!OK)
+ return TPM_RC_SIGNATURE;
+ else
+ return TPM_RC_SUCCESS;
+}
+#endif // ALG_SM2
+#if ALG_ECSCHNORR
+/* 10.2.12.3.9 BnValidateSignatureEcSchnorr() */
+/* This function is used to validate an EC Schnorr signature. */
+/* Error Returns Meaning */
+/* TPM_RC_SIGNATURE signature not valid */
+static TPM_RC
+BnValidateSignatureEcSchnorr(
+ bigNum bnR, // IN: r component of the signature
+ bigNum bnS, // IN: s component of the signature
+ TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature
+ bigCurve E, // IN: the curve used in the signature
+ // process
+ bigPoint ecQ, // IN: the public point of the key
+ const TPM2B_DIGEST *digest // IN: the digest that was signed
+ )
+{
+ BN_MAX(bnRn);
+ POINT(ecE);
+ BN_MAX(bnEx);
+ const ECC_CURVE_DATA *C = AccessCurveData(E);
+ bigConst order = CurveGetOrder(C);
+ UINT16 digestSize = CryptHashGetDigestSize(hashAlg);
+ HASH_STATE hashState;
+ TPM2B_TYPE(BUFFER, MAX(MAX_ECC_PARAMETER_BYTES, MAX_DIGEST_SIZE));
+ TPM2B_BUFFER Ex2 = {{sizeof(Ex2.t.buffer),{ 0 }}};
+ BOOL OK;
+ //
+ // E = [s]G - [r]Q
+ BnMod(bnR, order);
+ // Make -r = n - r
+ BnSub(bnRn, order, bnR);
+ // E = [s]G + [-r]Q
+ OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS;
+ // // reduce the x portion of E mod q
+ // OK = OK && BnMod(ecE->x, order);
+ // Convert to byte string
+ OK = OK && BnTo2B(ecE->x, &Ex2.b,
+ (NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order))));
+ if(OK)
+ {
+ // Ex = h(pE.x || digest)
+ CryptHashStart(&hashState, hashAlg);
+ CryptDigestUpdate(&hashState, Ex2.t.size, Ex2.t.buffer);
+ CryptDigestUpdate(&hashState, digest->t.size, digest->t.buffer);
+ Ex2.t.size = CryptHashEnd(&hashState, digestSize, Ex2.t.buffer);
+ SchnorrReduce(&Ex2.b, order);
+ BnFrom2B(bnEx, &Ex2.b);
+ // see if Ex matches R
+ OK = BnUnsignedCmp(bnEx, bnR) == 0;
+ }
+ return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE;
+}
+#endif // ALG_ECSCHNORR
+/* 10.2.12.3.10 CryptEccValidateSignature() */
+/* This function validates an EcDsa() or EcSchnorr() signature. The point Qin needs to have been
+ validated to be on the curve of curveId. */
+/* Error Returns Meaning */
+/* TPM_RC_SIGNATURE not a valid signature */
+LIB_EXPORT TPM_RC
+CryptEccValidateSignature(
+ TPMT_SIGNATURE *signature, // IN: signature to be verified
+ OBJECT *signKey, // IN: ECC key signed the hash
+ const TPM2B_DIGEST *digest // IN: digest that was signed
+ )
+{
+ CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
+ ECC_NUM(bnR);
+ ECC_NUM(bnS);
+ POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc);
+ bigConst order;
+ TPM_RC retVal;
+ if(E == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+ order = CurveGetOrder(AccessCurveData(E));
+ // // Make sure that the scheme is valid
+ switch(signature->sigAlg)
+ {
+ case TPM_ALG_ECDSA:
+#if ALG_ECSCHNORR
+ case TPM_ALG_ECSCHNORR:
+#endif
+#if ALG_SM2
+ case TPM_ALG_SM2:
+#endif
+ break;
+ default:
+ ERROR_RETURN(TPM_RC_SCHEME);
+ break;
+ }
+ // Can convert r and s after determining that the scheme is an ECC scheme. If
+ // this conversion doesn't work, it means that the unmarshaling code for
+ // an ECC signature is broken.
+ BnFrom2B(bnR, &signature->signature.ecdsa.signatureR.b);
+ BnFrom2B(bnS, &signature->signature.ecdsa.signatureS.b);
+ // r and s have to be greater than 0 but less than the curve order
+ if(BnEqualZero(bnR) || BnEqualZero(bnS))
+ ERROR_RETURN(TPM_RC_SIGNATURE);
+ if((BnUnsignedCmp(bnS, order) >= 0)
+ || (BnUnsignedCmp(bnR, order) >= 0))
+ ERROR_RETURN(TPM_RC_SIGNATURE);
+ switch(signature->sigAlg)
+ {
+ case TPM_ALG_ECDSA:
+ retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest);
+ break;
+#if ALG_ECSCHNORR
+ case TPM_ALG_ECSCHNORR:
+ retVal = BnValidateSignatureEcSchnorr(bnR, bnS,
+ signature->signature.any.hashAlg,
+ E, ecQ, digest);
+ break;
+#endif
+#if ALG_SM2
+ case TPM_ALG_SM2:
+ retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest);
+ break;
+#endif
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+ Exit:
+ CURVE_FREE(E);
+ return retVal;
+}
+/* 10.2.12.3.11 CryptEccCommitCompute() */
+/* This function performs the point multiply operations required by TPM2_Commit(). */
+/* If B or M is provided, they must be on the curve defined by curveId. This routine does not check
+ that they are on the curve and results are unpredictable if they are not. */
+/* It is a fatal error if r is NULL. If B is not NULL, then it is a fatal error if d is NULL or if K
+ and L are both NULL. If M is not NULL, then it is a fatal error if E is NULL. */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT if K, L or E was computed to be the point at infinity */
+/* TPM_RC_CANCELED a cancel indication was asserted during this function */
+LIB_EXPORT TPM_RC
+CryptEccCommitCompute(
+ TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q
+ TPMS_ECC_POINT *L, // OUT: [r]B
+ TPMS_ECC_POINT *E, // OUT: [r]M
+ TPM_ECC_CURVE curveId, // IN: the curve for the computations
+ TPMS_ECC_POINT *M, // IN: M (optional)
+ TPMS_ECC_POINT *B, // IN: B (optional)
+ TPM2B_ECC_PARAMETER *d, // IN: d (optional)
+ TPM2B_ECC_PARAMETER *r // IN: the computed r value (required)
+ )
+{
+ CURVE_INITIALIZED(curve, curveId); // Normally initialize E as the curve, but E means
+ // something else in this function
+ ECC_INITIALIZED(bnR, r);
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ //
+ // Validate that the required parameters are provided.
+ // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do
+ // E := [r]Q if both M and B are NULL.
+ pAssert(r != NULL && E != NULL);
+ // Initialize the output points in case they are not computed
+ ClearPoint2B(K);
+ ClearPoint2B(L);
+ ClearPoint2B(E);
+ // Sizes of the r parameter may not be zero
+ pAssert(r->t.size > 0);
+ // If B is provided, compute K=[d]B and L=[r]B
+ if(B != NULL)
+ {
+ ECC_INITIALIZED(bnD, d);
+ POINT_INITIALIZED(pB, B);
+ POINT(pK);
+ POINT(pL);
+ //
+ pAssert(d != NULL && K != NULL && L != NULL);
+ if(!BnIsOnCurve(pB, AccessCurveData(curve)))
+ ERROR_RETURN(TPM_RC_VALUE);
+ // do the math for K = [d]B
+ if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS)
+ goto Exit;
+ // Convert BN K to TPM2B K
+ BnPointTo2B(K, pK, curve);
+ // compute L= [r]B after checking for cancel
+ if(_plat__IsCanceled())
+ ERROR_RETURN(TPM_RC_CANCELED);
+ // compute L = [r]B
+ if(!BnIsValidPrivateEcc(bnR, curve))
+ ERROR_RETURN(TPM_RC_VALUE);
+ if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS)
+ goto Exit;
+ // Convert BN L to TPM2B L
+ BnPointTo2B(L, pL, curve);
+ }
+ if((M != NULL) || (B == NULL))
+ {
+ POINT_INITIALIZED(pM, M);
+ POINT(pE);
+ //
+ // Make sure that a place was provided for the result
+ pAssert(E != NULL);
+ // if this is the third point multiply, check for cancel first
+ if((B != NULL) && _plat__IsCanceled())
+ ERROR_RETURN(TPM_RC_CANCELED);
+ // If M provided, then pM will not be NULL and will compute E = [r]M.
+ // However, if M was not provided, then pM will be NULL and E = [r]G
+ // will be computed
+ if((retVal = BnPointMult(pE, pM, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS)
+ goto Exit;
+ // Convert E to 2B format
+ BnPointTo2B(E, pE, curve);
+ }
+ Exit:
+ CURVE_FREE(curve);
+ return retVal;
+}
+#endif // TPM_ALG_ECC
diff --git a/src/tpm2/crypto/openssl/CryptHash.c b/src/tpm2/crypto/openssl/CryptHash.c
new file mode 100644
index 0000000..cb5bd0f
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptHash.c
@@ -0,0 +1,871 @@
+/********************************************************************************/
+/* */
+/* Implementation of cryptographic functions for hashing. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptHash.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.13 CryptHash.c */
+/* 10.2.13.1 Description */
+/* This file contains implementation of cryptographic functions for hashing. */
+/* 10.2.13.2 Includes, Defines, and Types */
+#define _CRYPT_HASH_C_
+#include "Tpm.h"
+#include "CryptHash_fp.h"
+#include "CryptHash.h"
+#include "OIDs.h"
+
+/* Instance each of the hash descriptors based on the implemented algorithms */
+
+FOR_EACH_HASH(HASH_DEF_TEMPLATE)
+
+/* Instance a null def. */
+
+ HASH_DEF NULL_Def = {{0}};
+
+/* Create a table of pointers to the defined hash definitions */
+
+#define HASH_DEF_ENTRY(HASH, Hash) &Hash##_Def,
+PHASH_DEF HashDefArray[] = {
+ // for each implemented HASH, expands to: &HASH_Def,
+ FOR_EACH_HASH(HASH_DEF_ENTRY)
+ &NULL_Def
+};
+
+/* 10.2.13.3 Obligatory Initialization Functions */
+/* 10.2.13.3.1 CryptHashInit() */
+/* This function is called by _TPM_Init() do perform the initialization operations for the
+ library. */
+BOOL
+CryptHashInit(
+ void
+ )
+{
+ LibHashInit();
+ return TRUE;
+}
+/* 10.2.13.3.2 CryptHashStartup() */
+/* This function is called by TPM2_Startup(). It checks that the size of the HashDefArray() is
+ consistent with the HASH_COUNT. */
+BOOL
+CryptHashStartup(
+ void
+ )
+{
+ int i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1;
+ return (i == HASH_COUNT);
+}
+/* 10.2.13.4 Hash Information Access Functions */
+/* 10.2.13.4.1 Introduction */
+/* These functions provide access to the hash algorithm description information. */
+/* 10.2.13.4.2 CryptGetHashDef() */
+/* This function accesses the hash descriptor associated with a hash a algorithm. The function
+ returns a pointer to a null descriptor if hashAlg is TPM_ALG_NULL or not a defined algorithm. */
+
+PHASH_DEF
+CryptGetHashDef(
+ TPM_ALG_ID hashAlg
+ )
+{
+#define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def;
+ switch(hashAlg)
+ {
+ FOR_EACH_HASH(GET_DEF)
+ default:
+ return &NULL_Def;
+ }
+#undef GET_DEF
+}
+/* 10.2.13.4.3 CryptHashIsValidAlg() */
+/* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then
+ TPM_ALG_NULL is a valid hash. */
+/* Return Value Meaning */
+/* TRUE(1) hashAlg is a valid, implemented hash on this TPM */
+/* FALSE(0) hashAlg is not valid for this TPM */
+BOOL
+CryptHashIsValidAlg(
+ TPM_ALG_ID hashAlg, // IN: the algorithm to check
+ BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated
+ // as a valid hash
+ )
+{
+ if(hashAlg == TPM_ALG_NULL)
+ return flag;
+ return CryptGetHashDef(hashAlg) != &NULL_Def;
+}
+/* 10.2.13.4.4 CryptHashGetAlgByIndex() */
+/* This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes
+ that are not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return
+ the first implemented hash and an index of 2 will return the last. All other index values will
+ return TPM_ALG_NULL. */
+/* Return Value Meaning */
+/* TPM_ALG_xxx a hash algorithm */
+/* TPM_ALG_NULL this can be used as a stop value */
+LIB_EXPORT TPM_ALG_ID
+CryptHashGetAlgByIndex(
+ UINT32 index // IN: the index
+ )
+{
+ TPM_ALG_ID hashAlg;
+ if(index >= HASH_COUNT)
+ hashAlg = TPM_ALG_NULL;
+ else
+ hashAlg = HashDefArray[index]->hashAlg;
+ return hashAlg;
+}
+/* 10.2.13.4.5 CryptHashGetDigestSize() */
+/* Returns the size of the digest produced by the hash. If hashAlg is not a hash algorithm, the TPM
+ will FAIL. */
+/* Return Value Meaning */
+/* 0 TPM_ALG_NULL */
+/* > 0 the digest size */
+LIB_EXPORT UINT16
+CryptHashGetDigestSize(
+ TPM_ALG_ID hashAlg // IN: hash algorithm to look up
+ )
+{
+ return CryptGetHashDef(hashAlg)->digestSize;
+}
+/* 10.2.13.4.6 CryptHashGetBlockSize() */
+/* Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will
+ FAIL. */
+/* Return Value Meaning */
+/* 0 TPM_ALG_NULL */
+/* > 0 the digest size */
+LIB_EXPORT UINT16
+CryptHashGetBlockSize(
+ TPM_ALG_ID hashAlg // IN: hash algorithm to look up
+ )
+{
+ return CryptGetHashDef(hashAlg)->blockSize;
+}
+/* 10.2.13.4.7 CryptHashGetOid() */
+/* This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs are full OID
+ values including the Tag (0x06) and length byte. */
+#if 0 // libtpms added
+LIB_EXPORT const BYTE *
+CryptHashGetOid(
+ TPM_ALG_ID hashAlg
+ )
+{
+ return CryptGetHashDef(hashAlg)->OID;
+}
+#endif // libtpms added
+/* 10.2.13.4.8 CryptHashGetContextAlg() */
+/* This function returns the hash algorithm associated with a hash context. */
+#if 0 // libtpms added
+TPM_ALG_ID
+CryptHashGetContextAlg(
+ PHASH_STATE state // IN: the context to check
+ )
+{
+ return state->hashAlg;
+}
+#endif // libtpms added
+/* 10.2.13.5 State Import and Export */
+/* 10.2.13.5.1 CryptHashCopyState */
+/* This function is used to clone a HASH_STATE. */
+#if 0 // libtpms added
+LIB_EXPORT void
+CryptHashCopyState(
+ HASH_STATE *out, // OUT: destination of the state
+ const HASH_STATE *in // IN: source of the state
+ )
+{
+ pAssert(out->type == in->type);
+ out->hashAlg = in->hashAlg;
+ out->def = in->def;
+ if(in->hashAlg != TPM_ALG_NULL)
+ {
+ HASH_STATE_COPY(out, in);
+ }
+ if(in->type == HASH_STATE_HMAC)
+ {
+ const HMAC_STATE *hIn = (HMAC_STATE *)in;
+ HMAC_STATE *hOut = (HMAC_STATE *)out;
+ hOut->hmacKey = hIn->hmacKey;
+ }
+ return;
+}
+#endif // libtpms added
+#if 0 // libtpms added
+/* 10.2.13.5.2 CryptHashExportState() */
+/* This function is used to export a hash or HMAC hash state. This function would be called when
+ preparing to context save a sequence object. */
+void
+CryptHashExportState(
+ PCHASH_STATE internalFmt, // IN: the hash state formatted for use by
+ // library
+ PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state
+ )
+{
+ BYTE *outBuf = (BYTE *)externalFmt;
+ //
+ cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));
+ // the following #define is used to move data from an aligned internal data
+ // structure to a byte buffer (external format data.
+#define CopyToOffset(value) \
+ memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value, \
+ sizeof(internalFmt->value))
+ // Copy the hashAlg
+ CopyToOffset(hashAlg);
+ CopyToOffset(type);
+#ifdef HASH_STATE_SMAC
+ if(internalFmt->type == HASH_STATE_SMAC)
+ {
+ memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
+ return;
+
+ }
+#endif
+ if(internalFmt->type == HASH_STATE_HMAC)
+ {
+ HMAC_STATE *from = (HMAC_STATE *)internalFmt;
+ memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey,
+ sizeof(from->hmacKey));
+ }
+ if(internalFmt->hashAlg != TPM_ALG_NULL)
+ HASH_STATE_EXPORT(externalFmt, internalFmt);
+}
+/* 10.2.13.5.3 CryptHashImportState() */
+/* This function is used to import the hash state. This function would be called to import a hash
+ state when the context of a sequence object was being loaded. */
+void
+CryptHashImportState(
+ PHASH_STATE internalFmt, // OUT: the hash state formatted for use by
+ // the library
+ PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state
+ )
+{
+ BYTE *inBuf = (BYTE *)externalFmt;
+ //
+#define CopyFromOffset(value) \
+ memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)], \
+ sizeof(internalFmt->value))
+
+ // Copy the hashAlg of the byte-aligned input structure to the structure-aligned
+ // internal structure.
+ CopyFromOffset(hashAlg);
+ CopyFromOffset(type);
+ if(internalFmt->hashAlg != TPM_ALG_NULL)
+ {
+#ifdef HASH_STATE_SMAC
+ if(internalFmt->type == HASH_STATE_SMAC)
+ {
+ memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
+ return;
+ }
+#endif
+ internalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
+ HASH_STATE_IMPORT(internalFmt, inBuf);
+ if(internalFmt->type == HASH_STATE_HMAC)
+ {
+ HMAC_STATE *to = (HMAC_STATE *)internalFmt;
+ memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)],
+ sizeof(to->hmacKey));
+ }
+ }
+}
+#endif // libtpms added
+/* 10.2.13.6 State Modification Functions */
+/* 10.2.13.6.1 HashEnd() */
+/* Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function
+ is used to complete the hash and only return a partial digest. The return value is the size of
+ the data copied. */
+static UINT16
+HashEnd(
+ PHASH_STATE hashState, // IN: the hash state
+ UINT32 dOutSize, // IN: the size of receive buffer
+ PBYTE dOut // OUT: the receive buffer
+ )
+{
+ BYTE temp[MAX_DIGEST_SIZE];
+ if((hashState->hashAlg == TPM_ALG_NULL)
+ || (hashState->type != HASH_STATE_HASH))
+ dOutSize = 0;
+ if(dOutSize > 0)
+ {
+ hashState->def = CryptGetHashDef(hashState->hashAlg);
+ // Set the final size
+ dOutSize = MIN(dOutSize, hashState->def->digestSize);
+ // Complete into the temp buffer and then copy
+ HASH_END(hashState, temp);
+ // Don't want any other functions calling the HASH_END method
+ // directly.
+#undef HASH_END
+ memcpy(dOut, &temp, dOutSize);
+ }
+ hashState->type = HASH_STATE_EMPTY;
+ return (UINT16)dOutSize;
+}
+/* 10.2.13.6.2 CryptHashStart() */
+/* Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect,
+ the value of stateSize in hashState is updated to indicate the number of bytes of state that were
+ saved. This function calls GetHashServer() and that function will put the TPM into failure mode
+ if the hash algorithm is not supported. */
+/* This function does not use the sequence parameter. If it is necessary to import or export
+ context, this will start the sequence in a local state and export the state to the input
+ buffer. Will need to add a flag to the state structure to indicate that it needs to be imported
+ before it can be used. (BLEH). */
+/* Return Value Meaning */
+/* 0 hash is TPM_ALG_NULL */
+/* >0 digest size */
+LIB_EXPORT UINT16
+CryptHashStart(
+ PHASH_STATE hashState, // OUT: the running hash state
+ TPM_ALG_ID hashAlg // IN: hash algorithm
+ )
+{
+ UINT16 retVal;
+
+ TEST(hashAlg);
+
+ hashState->hashAlg = hashAlg;
+ if(hashAlg == TPM_ALG_NULL)
+ {
+ retVal = 0;
+ }
+ else
+ {
+ hashState->def = CryptGetHashDef(hashAlg);
+ HASH_START(hashState);
+ retVal = hashState->def->digestSize;
+ }
+#undef HASH_START
+ hashState->type = HASH_STATE_HASH;
+ return retVal;
+}
+/* 10.2.13.6.3 CryptDigestUpdate() */
+/* Add data to a hash or HMAC, SMAC stack. */
+void
+CryptDigestUpdate(
+ PHASH_STATE hashState, // IN: the hash context information
+ UINT32 dataSize, // IN: the size of data to be added
+ const BYTE *data // IN: data to be hashed
+ )
+{
+ if(hashState->hashAlg != TPM_ALG_NULL)
+ {
+ if((hashState->type == HASH_STATE_HASH)
+ || (hashState->type == HASH_STATE_HMAC))
+ HASH_DATA(hashState, dataSize, (BYTE *)data);
+#if SMAC_IMPLEMENTED
+ else if(hashState->type == HASH_STATE_SMAC)
+ (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state,
+ dataSize, data);
+#endif // SMAC_IMPLEMENTED
+ else
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+ return;
+}
+/* 10.2.13.6.4 CryptHashEnd() */
+/* Complete a hash or HMAC computation. This function will place the smaller of digestSize or the
+ size of the digest in dOut. The number of bytes in the placed in the buffer is returned. If there
+ is a failure, the returned value is <= 0. */
+/* Return Value Meaning */
+/* 0 no data returned */
+/* > 0 the number of bytes in the digest or dOutSize, whichever is smaller */
+LIB_EXPORT UINT16
+CryptHashEnd(
+ PHASH_STATE hashState, // IN: the state of hash stack
+ UINT32 dOutSize, // IN: size of digest buffer
+ BYTE *dOut // OUT: hash digest
+ )
+{
+ pAssert(hashState->type == HASH_STATE_HASH);
+ return HashEnd(hashState, dOutSize, dOut);
+}
+/* 10.2.13.6.5 CryptHashBlock() */
+/* Start a hash, hash a single block, update digest and return the size of the results. */
+/* The digestSize parameter can be smaller than the digest. If so, only the more significant
+ bytes are returned. */
+/* Return Value Meaning */
+/* >= 0 number of bytes placed in dOut */
+LIB_EXPORT UINT16
+CryptHashBlock(
+ TPM_ALG_ID hashAlg, // IN: The hash algorithm
+ UINT32 dataSize, // IN: size of buffer to hash
+ const BYTE *data, // IN: the buffer to hash
+ UINT32 dOutSize, // IN: size of the digest buffer
+ BYTE *dOut // OUT: digest buffer
+ )
+{
+ HASH_STATE state;
+ CryptHashStart(&state, hashAlg);
+ CryptDigestUpdate(&state, dataSize, data);
+ return HashEnd(&state, dOutSize, dOut);
+}
+/* 10.2.13.6.6 CryptDigestUpdate2B() */
+/* This function updates a digest (hash or HMAC) with a TPM2B. */
+/* This function can be used for both HMAC and hash functions so the digestState is void so that
+ either state type can be passed. */
+LIB_EXPORT void
+CryptDigestUpdate2B(
+ PHASH_STATE state, // IN: the digest state
+ const TPM2B *bIn // IN: 2B containing the data
+ )
+{
+ // Only compute the digest if a pointer to the 2B is provided.
+ // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change
+ // to the digest occurs. This function should not provide a buffer if bIn is
+ // not provided.
+ pAssert(bIn != NULL);
+ CryptDigestUpdate(state, bIn->size, bIn->buffer);
+ return;
+}
+/* 10.2.13.6.7 CryptHashEnd2B() */
+/* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the
+ most common use and this is provided for specification clarity. digest.size should be set to
+ indicate the number of bytes to place in the buffer */
+/* Return Value Meaning */
+/* >=0 the number of bytes placed in digest.buffer */
+LIB_EXPORT UINT16
+CryptHashEnd2B(
+ PHASH_STATE state, // IN: the hash state
+ P2B digest // IN: the size of the buffer Out: requested
+ // number of bytes
+ )
+{
+ return CryptHashEnd(state, digest->size, digest->buffer);
+}
+/* 10.2.13.6.8 CryptDigestUpdateInt() */
+/* This function is used to include an integer value to a hash stack. The function marshals the
+ integer into its canonical form before calling CryptDigestUpdate(). */
+LIB_EXPORT void
+CryptDigestUpdateInt(
+ void *state, // IN: the state of hash stack
+ UINT32 intSize, // IN: the size of 'intValue' in bytes
+ UINT64 intValue // IN: integer value to be hashed
+ )
+{
+#if LITTLE_ENDIAN_TPM
+ intValue = REVERSE_ENDIAN_64(intValue);
+#endif
+ CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]);
+}
+/* 10.2.13.7 HMAC Functions */
+/* 10.2.13.7.1 CryptHmacStart() */
+/* This function is used to start an HMAC using a temp hash context. The function does the
+ initialization of the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. */
+/* The function returns the number of bytes in a digest produced by hashAlg. */
+/* Return Value Meaning */
+/* >= 0 number of bytes in digest produced by hashAlg (may be zero) */
+LIB_EXPORT UINT16
+CryptHmacStart(
+ PHMAC_STATE state, // IN/OUT: the state buffer
+ TPM_ALG_ID hashAlg, // IN: the algorithm to use
+ UINT16 keySize, // IN: the size of the HMAC key
+ const BYTE *key // IN: the HMAC key
+ )
+{
+ PHASH_DEF hashDef;
+ BYTE * pb;
+ UINT32 i;
+ //
+ hashDef = CryptGetHashDef(hashAlg);
+ if(hashDef->digestSize != 0)
+ {
+ // If the HMAC key is larger than the hash block size, it has to be reduced
+ // to fit. The reduction is a digest of the hashKey.
+ if(keySize > hashDef->blockSize)
+ {
+ // if the key is too big, reduce it to a digest of itself
+ state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key,
+ hashDef->digestSize,
+ state->hmacKey.t.buffer);
+ }
+ else
+ {
+ memcpy(state->hmacKey.t.buffer, key, keySize);
+ state->hmacKey.t.size = keySize;
+ }
+ // XOR the key with iPad (0x36)
+ pb = state->hmacKey.t.buffer;
+ for(i = state->hmacKey.t.size; i > 0; i--)
+ *pb++ ^= 0x36;
+
+ // if the keySize is smaller than a block, fill the rest with 0x36
+ for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--)
+ *pb++ = 0x36;
+
+ // Increase the oPadSize to a full block
+ state->hmacKey.t.size = hashDef->blockSize;
+
+ // Start a new hash with the HMAC key
+ // This will go in the caller's state structure and may be a sequence or not
+ CryptHashStart((PHASH_STATE)state, hashAlg);
+ CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size,
+ state->hmacKey.t.buffer);
+ // XOR the key block with 0x5c ^ 0x36
+ for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--)
+ *pb++ ^= (0x5c ^ 0x36);
+ }
+ // Set the hash algorithm
+ state->hashState.hashAlg = hashAlg;
+ // Set the hash state type
+ state->hashState.type = HASH_STATE_HMAC;
+
+ return hashDef->digestSize;
+}
+/* 10.2.13.7.2 CryptHmacEnd() */
+/* This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will then add the oPadKey and the completed digest and return the results in dOut. It will not return more than dOutSize bytes. */
+/* Return Value Meaning */
+/* >= 0 number of bytes in dOut (may be zero) */
+LIB_EXPORT UINT16
+CryptHmacEnd(
+ PHMAC_STATE state, // IN: the hash state buffer
+ UINT32 dOutSize, // IN: size of digest buffer
+ BYTE *dOut // OUT: hash digest
+ )
+{
+ BYTE temp[MAX_DIGEST_SIZE];
+ PHASH_STATE hState = (PHASH_STATE)&state->hashState;
+
+#if SMAC_IMPLEMENTED
+ if(hState->type == HASH_STATE_SMAC)
+ return (state->hashState.state.smac.smacMethods.end)
+ (&state->hashState.state.smac.state,
+ dOutSize,
+ dOut);
+#endif
+ pAssert(hState->type == HASH_STATE_HMAC);
+ hState->def = CryptGetHashDef(hState->hashAlg);
+ // Change the state type for completion processing
+ hState->type = HASH_STATE_HASH;
+ if(hState->hashAlg == TPM_ALG_NULL)
+ dOutSize = 0;
+ else
+ {
+
+ // Complete the current hash
+ HashEnd(hState, hState->def->digestSize, temp);
+ // Do another hash starting with the oPad
+ CryptHashStart(hState, hState->hashAlg);
+ CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer);
+ CryptDigestUpdate(hState, hState->def->digestSize, temp);
+ }
+ return HashEnd(hState, dOutSize, dOut);
+}
+/* 10.2.13.7.3 CryptHmacStart2B() */
+/* This function starts an HMAC and returns the size of the digest that will be produced. */
+/* This function is provided to support the most common use of starting an HMAC with a TPM2B key. */
+/* The caller must provide a block of memory in which the hash sequence state is kept. The caller
+ should not alter the contents of this buffer until the hash sequence is completed or
+ abandoned. */
+/* Return Value Meaning */
+/* > 0 the digest size of the algorithm */
+/* = 0 the hashAlg was TPM_ALG_NULL */
+LIB_EXPORT UINT16
+CryptHmacStart2B(
+ PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used
+ // in HMAC update and completion
+ TPMI_ALG_HASH hashAlg, // IN: hash algorithm
+ P2B key // IN: HMAC key
+ )
+{
+ return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer);
+}
+ /* 10.2.13.7.4 CryptHmacEnd2B() */
+ /* This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is the most common use. */
+ /* Return Value Meaning */
+ /* >=0 the number of bytes placed in digest */
+LIB_EXPORT UINT16
+CryptHmacEnd2B(
+ PHMAC_STATE hmacState, // IN: the state of HMAC stack
+ P2B digest // OUT: HMAC
+ )
+{
+ return CryptHmacEnd(hmacState, digest->size, digest->buffer);
+}
+/* 10.2.13.8 Mask and Key Generation Functions */
+/* 10.2.13.8.1 CryptMGF_KDF() */
+/* This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are T(n) = T(n-1)
+ || H(seed || counter) with the difference being that, with KDF1, counter starts at 0 but with
+ KDF2, counter starts at 1. The caller determines which version by setting the initial value of
+ counter to either 0 or 1. */
+/* Return Value Meaning */
+/* 0 hash algorithm was TPM_ALG_NULL */
+/* > 0 should be the same as mSize */
+LIB_EXPORT UINT16
+CryptMGF_KDF(
+ UINT32 mSize, // IN: length of the mask to be produced
+ BYTE *mask, // OUT: buffer to receive the mask
+ TPM_ALG_ID hashAlg, // IN: hash to use
+ UINT32 seedSize, // IN: size of the seed
+ BYTE *seed, // IN: seed size
+ UINT32 counter // IN: counter initial value
+ )
+{
+ HASH_STATE hashState;
+ PHASH_DEF hDef = CryptGetHashDef(hashAlg);
+ UINT32 hLen;
+ UINT32 bytes;
+ //
+ // If there is no digest to compute return
+ if((hDef->digestSize == 0) || (mSize == 0))
+ return 0;
+ if(counter != 0)
+ counter = 1;
+ hLen = hDef->digestSize;
+ for(bytes = 0; bytes < mSize; bytes += hLen)
+ {
+ // Start the hash and include the seed and counter
+ CryptHashStart(&hashState, hashAlg);
+ CryptDigestUpdate(&hashState, seedSize, seed);
+ CryptDigestUpdateInt(&hashState, 4, counter);
+ // Get as much as will fit.
+ CryptHashEnd(&hashState, MIN((mSize - bytes), hLen),
+ &mask[bytes]);
+ counter++;
+ }
+ return (UINT16)mSize;
+}
+/* 10.2.13.8.2 CryptKDFa() */
+/* This function performs the key generation according to Part 1 of the TPM specification. */
+/* This function returns the number of bytes generated which may be zero. */
+/* The key and keyStream pointers are not allowed to be NULL. The other pointer values may be
+ NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). */
+/* The once parameter is set to allow incremental generation of a large value. If this flag is
+ TRUE, sizeInBits will be used in the HMAC computation but only one iteration of the KDF is
+ performed. This would be used for XOR obfuscation so that the mask value can be generated in
+ digest-sized chunks rather than having to be generated all at once in an arbitrarily large
+ buffer and then XORed into the result. If once is TRUE, then sizeInBits must be a multiple of
+ 8. */
+/* Any error in the processing of this command is considered fatal. */
+/* Return Value Meaning */
+/* 0 hash algorithm is not supported or is TPM_ALG_NULL */
+/* > 0 the number of bytes in the keyStream buffer */
+LIB_EXPORT UINT16
+CryptKDFa(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC
+ const TPM2B *key, // IN: HMAC key
+ const TPM2B *label, // IN: a label for the KDF
+ const TPM2B *contextU, // IN: context U
+ const TPM2B *contextV, // IN: context V
+ UINT32 sizeInBits, // IN: size of generated key in bits
+ BYTE *keyStream, // OUT: key buffer
+ UINT32 *counterInOut, // IN/OUT: caller may provide the iteration
+ // counter for incremental operations to
+ // avoid large intermediate buffers.
+ UINT16 blocks // IN: If non-zero, this is the maximum number
+ // of blocks to be returned, regardless
+ // of sizeInBits
+ )
+{
+ UINT32 counter = 0; // counter value
+ INT16 bytes; // number of bytes to produce
+ UINT16 generated; // number of bytes generated
+ BYTE *stream = keyStream;
+ HMAC_STATE hState;
+ UINT16 digestSize = CryptHashGetDigestSize(hashAlg);
+
+ pAssert(key != NULL && keyStream != NULL);
+
+ TEST(TPM_ALG_KDF1_SP800_108);
+
+ if(digestSize == 0)
+ return 0;
+
+ if(counterInOut != NULL)
+ counter = *counterInOut;
+
+ // If the size of the request is larger than the numbers will handle,
+ // it is a fatal error.
+ pAssert(((sizeInBits + 7) / 8) <= INT16_MAX);
+
+ // The number of bytes to be generated is the smaller of the sizeInBits bytes or
+ // the number of requested blocks. The number of blocks is the smaller of the
+ // number requested or the number allowed by sizeInBits. A partial block is
+ // a full block.
+ bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
+ generated = bytes;
+
+ // Generate required bytes
+ for(; bytes > 0; bytes -= digestSize)
+ {
+ counter++;
+ // Start HMAC
+ if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
+ return 0;
+ // Adding counter
+ CryptDigestUpdateInt(&hState.hashState, 4, counter);
+
+ // Adding label
+ if(label != NULL)
+ HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer);
+ // Add a null. SP108 is not very clear about when the 0 is needed but to
+ // make this like the previous version that did not add an 0x00 after
+ // a null-terminated string, this version will only add a null byte
+ // if the label parameter did not end in a null byte, or if no label
+ // is present.
+ if((label == NULL)
+ || (label->size == 0)
+ || (label->buffer[label->size - 1] != 0))
+ CryptDigestUpdateInt(&hState.hashState, 1, 0);
+ // Adding contextU
+ if(contextU != NULL)
+ HASH_DATA(&hState.hashState, contextU->size, contextU->buffer);
+ // Adding contextV
+ if(contextV != NULL)
+ HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);
+ // Adding size in bits
+ CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);
+
+ // Complete and put the data in the buffer
+ CryptHmacEnd(&hState, bytes, stream);
+ stream = &stream[digestSize];
+ }
+ // Masking in the KDF is disabled. If the calling function wants something
+ // less than even number of bytes, then the caller should do the masking
+ // because there is no universal way to do it here
+ if(counterInOut != NULL)
+ *counterInOut = counter;
+ return generated;
+}
+/* 10.2.13.8.3 CryptKDFe() */
+/* This function implements KDFe() as defined in TPM specification part 1. */
+/* This function returns the number of bytes generated which may be zero. */
+/* The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be
+ NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any
+ error in the processing of this command is considered fatal. */
+/* Return Value Meaning */
+/* 0 hash algorithm is not supported or is TPM_ALG_NULL */
+/* > 0 the number of bytes in the keyStream buffer */
+LIB_EXPORT UINT16
+CryptKDFe(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC
+ TPM2B *Z, // IN: Z
+ const TPM2B *label, // IN: a label value for the KDF
+ TPM2B *partyUInfo, // IN: PartyUInfo
+ TPM2B *partyVInfo, // IN: PartyVInfo
+ UINT32 sizeInBits, // IN: size of generated key in bits
+ BYTE *keyStream // OUT: key buffer
+ )
+{
+ HASH_STATE hashState;
+ PHASH_DEF hashDef = CryptGetHashDef(hashAlg);
+
+ UINT32 counter = 0; // counter value
+ UINT16 hLen;
+ BYTE *stream = keyStream;
+ INT16 bytes; // number of bytes to generate
+
+ pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX);
+ //
+ hLen = hashDef->digestSize;
+ bytes = (INT16)((sizeInBits + 7) / 8);
+ if(hashAlg == TPM_ALG_NULL || bytes == 0)
+ return 0;
+
+ // Generate required bytes
+ //The inner loop of that KDF uses:
+ // Hash[i] := H(counter | Z | OtherInfo) (5)
+ // Where:
+ // Hash[i] the hash generated on the i-th iteration of the loop.
+ // H() an approved hash function
+ // counter a 32-bit counter that is initialized to 1 and incremented
+ // on each iteration
+ // Z the X coordinate of the product of a public ECC key and a
+ // different private ECC key.
+ // OtherInfo a collection of qualifying data for the KDF defined below.
+ // In this specification, OtherInfo will be constructed by:
+ // OtherInfo := Use | PartyUInfo | PartyVInfo
+ for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
+ {
+ if(bytes < hLen)
+ hLen = bytes;
+ counter++;
+ // Do the hash
+ CryptHashStart(&hashState, hashAlg);
+ // Add counter
+ CryptDigestUpdateInt(&hashState, 4, counter);
+
+ // Add Z
+ if(Z != NULL)
+ CryptDigestUpdate2B(&hashState, Z);
+ // Add label
+ if(label != NULL)
+ CryptDigestUpdate2B(&hashState, label);
+ // Add a null. SP108 is not very clear about when the 0 is needed but to
+ // make this like the previous version that did not add an 0x00 after
+ // a null-terminated string, this version will only add a null byte
+ // if the label parameter did not end in a null byte, or if no label
+ // is present.
+ if((label == NULL)
+ || (label->size == 0)
+ || (label->buffer[label->size - 1] != 0))
+ CryptDigestUpdateInt(&hashState, 1, 0);
+ // Add PartyUInfo
+ if(partyUInfo != NULL)
+ CryptDigestUpdate2B(&hashState, partyUInfo);
+
+ // Add PartyVInfo
+ if(partyVInfo != NULL)
+ CryptDigestUpdate2B(&hashState, partyVInfo);
+
+ // Compute Hash. hLen was changed to be the smaller of bytes or hLen
+ // at the start of each iteration.
+ CryptHashEnd(&hashState, hLen, stream);
+ }
+
+ // Mask off bits if the required bits is not a multiple of byte size
+ if((sizeInBits % 8) != 0)
+ keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
+
+ return (UINT16)((sizeInBits + 7) / 8);
+}
diff --git a/src/tpm2/crypto/openssl/CryptPrime.c b/src/tpm2/crypto/openssl/CryptPrime.c
new file mode 100644
index 0000000..0de9ef2
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptPrime.c
@@ -0,0 +1,440 @@
+/********************************************************************************/
+/* */
+/* Code for prime validation. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptPrime.c 1529 2019-11-21 23:29:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+/* 10.2.14 CryptPrime.c */
+/* 10.2.14.1 Introduction */
+/* This file contains the code for prime validation. */
+
+#include "Tpm.h"
+#include "CryptPrime_fp.h"
+//#define CPRI_PRIME
+//#include "PrimeTable.h"
+#include "CryptPrimeSieve_fp.h"
+extern const uint32_t s_LastPrimeInTable;
+extern const uint32_t s_PrimeTableSize;
+extern const uint32_t s_PrimesInTable;
+extern const unsigned char s_PrimeTable[];
+extern bigConst s_CompositeOfSmallPrimes;
+
+/* 10.2.14.1.1 Root2() */
+/* This finds ceil(sqrt(n)) to use as a stopping point for searching the prime table. */
+static uint32_t
+Root2(
+ uint32_t n
+ )
+{
+ int32_t last = (int32_t)(n >> 2);
+ int32_t next = (int32_t)(n >> 1);
+ int32_t diff;
+ int32_t stop = 10;
+ //
+ // get a starting point
+ for(; next != 0; last >>= 1, next >>= 2);
+ last++;
+ do
+ {
+ next = (last + (n / last)) >> 1;
+ diff = next - last;
+ last = next;
+ if(stop-- == 0)
+ FAIL(FATAL_ERROR_INTERNAL);
+ } while(diff < -1 || diff > 1);
+ if((n / next) > (unsigned)next)
+ next++;
+ pAssert(next != 0);
+ pAssert(((n / next) <= (unsigned)next) && (n / (next + 1) < (unsigned)next));
+ return next;
+}
+/* 10.2.14.1.2 IsPrimeInt() */
+/* This will do a test of a word of up to 32-bits in size. */
+BOOL
+IsPrimeInt(
+ uint32_t n
+ )
+{
+ uint32_t i;
+ uint32_t stop;
+ if(n < 3 || ((n & 1) == 0))
+ return (n == 2);
+ if(n <= s_LastPrimeInTable)
+ {
+ n >>= 1;
+ return ((s_PrimeTable[n >> 3] >> (n & 7)) & 1);
+ }
+ // Need to search
+ stop = Root2(n) >> 1;
+ // starting at 1 is equivalent to staring at (1 << 1) + 1 = 3
+ for(i = 1; i < stop; i++)
+ {
+ if((s_PrimeTable[i >> 3] >> (i & 7)) & 1)
+ // see if this prime evenly divides the number
+ if((n % ((i << 1) + 1)) == 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+#if !RSA_KEY_SIEVE // libtpms added
+/* 10.2.14.1.3 BnIsProbablyPrime() */
+/* This function is used when the key sieve is not implemented. This function Will try to eliminate
+ some of the obvious things before going on to perform MillerRabin() as a final verification of
+ primeness. */
+BOOL
+BnIsProbablyPrime(
+ bigNum prime, // IN:
+ RAND_STATE *rand // IN: the random state just
+ // in case Miller-Rabin is required
+ )
+{
+#if RADIX_BITS > 32
+ if(BnUnsignedCmpWord(prime, UINT32_MAX) <= 0)
+#else
+ if(BnGetSize(prime) == 1)
+#endif
+ return IsPrimeInt((uint32_t)prime->d[0]);
+ if(BnIsEven(prime))
+ return FALSE;
+ if(BnUnsignedCmpWord(prime, s_LastPrimeInTable) <= 0)
+ {
+ crypt_uword_t temp = prime->d[0] >> 1;
+ return ((s_PrimeTable[temp >> 3] >> (temp & 7)) & 1);
+ }
+ {
+ BN_VAR(n, LARGEST_NUMBER_BITS);
+ BnGcd(n, prime, s_CompositeOfSmallPrimes);
+ if(!BnEqualWord(n, 1))
+ return FALSE;
+ }
+ return MillerRabin(prime, rand);
+}
+#endif // libtpms added
+/* 10.2.14.1.4 MillerRabinRounds() */
+/* Function returns the number of Miller-Rabin rounds necessary to give an error probability equal
+ to the security strength of the prime. These values are from FIPS 186-3. */
+UINT32
+MillerRabinRounds(
+ UINT32 bits // IN: Number of bits in the RSA prime
+ )
+{
+ if(bits < 511) return 8; // don't really expect this
+ if(bits < 1536) return 5; // for 512 and 1K primes
+ return 4; // for 3K public modulus and greater
+}
+/* 10.2.14.1.5 MillerRabin() */
+/* This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the
+ number. In all likelihood, if the number is not prime, the first test fails. */
+/* Return Values Meaning */
+/* TRUE probably prime */
+/* FALSE composite */
+BOOL
+MillerRabin(
+ bigNum bnW,
+ RAND_STATE *rand
+ )
+{
+ BN_MAX(bnWm1);
+ BN_PRIME(bnM);
+ BN_PRIME(bnB);
+ BN_PRIME(bnZ);
+ BOOL ret = FALSE; // Assumed composite for easy exit
+ unsigned int a;
+ unsigned int j;
+ int wLen;
+ int i;
+ int iterations = MillerRabinRounds(BnSizeInBits(bnW));
+ //
+ INSTRUMENT_INC(MillerRabinTrials[PrimeIndex]);
+
+ pAssert(bnW->size > 1);
+ // Let a be the largest integer such that 2^a divides w1.
+ BnSubWord(bnWm1, bnW, 1);
+ pAssert(bnWm1->size != 0);
+
+ // Since w is odd (w-1) is even so start at bit number 1 rather than 0
+ // Get the number of bits in bnWm1 so that it doesn't have to be recomputed
+ // on each iteration.
+ i = (int)(bnWm1->size * RADIX_BITS);
+ // Now find the largest power of 2 that divides w1
+ for(a = 1;
+ (a < (bnWm1->size * RADIX_BITS)) &&
+ (BnTestBit(bnWm1, a) == 0);
+ a++);
+ // 2. m = (w1) / 2^a
+ BnShiftRight(bnM, bnWm1, a);
+ // 3. wlen = len (w).
+ wLen = BnSizeInBits(bnW);
+ // 4. For i = 1 to iterations do
+ for(i = 0; i < iterations; i++)
+ {
+ // 4.1 Obtain a string b of wlen bits from an RBG.
+ // Ensure that 1 < b < w1.
+ // 4.2 If ((b <= 1) or (b >= w1)), then go to step 4.1.
+ while(BnGetRandomBits(bnB, wLen, rand) && ((BnUnsignedCmpWord(bnB, 1) <= 0)
+ || (BnUnsignedCmp(bnB, bnWm1) >= 0)));
+ if(g_inFailureMode)
+ return FALSE;
+
+ // 4.3 z = b^m mod w.
+ // if ModExp fails, then say this is not
+ // prime and bail out.
+ BnModExp(bnZ, bnB, bnM, bnW);
+
+ // 4.4 If ((z == 1) or (z = w == 1)), then go to step 4.7.
+ if((BnUnsignedCmpWord(bnZ, 1) == 0)
+ || (BnUnsignedCmp(bnZ, bnWm1) == 0))
+ goto step4point7;
+ // 4.5 For j = 1 to a 1 do.
+ for(j = 1; j < a; j++)
+ {
+ // 4.5.1 z = z^2 mod w.
+ BnModMult(bnZ, bnZ, bnZ, bnW);
+ // 4.5.2 If (z = w1), then go to step 4.7.
+ if(BnUnsignedCmp(bnZ, bnWm1) == 0)
+ goto step4point7;
+ // 4.5.3 If (z = 1), then go to step 4.6.
+ if(BnEqualWord(bnZ, 1))
+ goto step4point6;
+ }
+ // 4.6 Return COMPOSITE.
+ step4point6:
+ INSTRUMENT_INC(failedAtIteration[i]);
+ goto end;
+ // 4.7 Continue. Comment: Increment i for the do-loop in step 4.
+ step4point7:
+ continue;
+ }
+ // 5. Return PROBABLY PRIME
+ ret = TRUE;
+ end:
+ return ret;
+}
+#if ALG_RSA
+/* 10.2.14.1.6 RsaCheckPrime() */
+/* This will check to see if a number is prime and appropriate for an RSA prime. */
+/* This has different functionality based on whether we are using key sieving or not. If not, the
+ number checked to see if it is divisible by the public exponent, then the number is adjusted
+ either up or down in order to make it a better candidate. It is then checked for being probably
+ prime. */
+/* If sieving is used, the number is used to root a sieving process. */
+TPM_RC
+RsaCheckPrime(
+ bigNum prime,
+ UINT32 exponent,
+ RAND_STATE *rand
+ )
+{
+#if !RSA_KEY_SIEVE
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ UINT32 modE = BnModWord(prime, exponent);
+ NOT_REFERENCED(rand);
+ if(modE == 0)
+ // evenly divisible so add two keeping the number odd
+ BnAddWord(prime, prime, 2);
+ // want 0 != (p - 1) mod e
+ // which is 1 != p mod e
+ else if(modE == 1)
+ // subtract 2 keeping number odd and insuring that
+ // 0 != (p - 1) mod e
+ BnSubWord(prime, prime, 2);
+ if(BnIsProbablyPrime(prime, rand) == 0)
+ ERROR_RETURN(g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_VALUE);
+ Exit:
+ return retVal;
+#else
+ return PrimeSelectWithSieve(prime, exponent, rand);
+#endif
+}
+/*
+ * RsaAdjustPrimeCandidate_PreRev155 is the pre-rev.155 algorithm used; we
+ * still have to use it for old seeds to maintain backwards compatibility.
+ */
+static void
+RsaAdjustPrimeCandidate_PreRev155(
+ bigNum prime
+ )
+{
+ UINT16 highBytes;
+ crypt_uword_t *msw = &prime->d[prime->size - 1];
+#define MASK (MAX_CRYPT_UWORD >> (RADIX_BITS - 16))
+ highBytes = *msw >> (RADIX_BITS - 16);
+ // This is fixed point arithmetic on 16-bit values
+ highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16;
+ highBytes += 0xB505;
+ *msw = ((crypt_uword_t)(highBytes) << (RADIX_BITS - 16)) + (*msw & MASK);
+ prime->d[0] |= 1;
+}
+
+/* 10.2.14.1.7 RsaAdjustPrimeCandidate() */
+
+/* For this math, we assume that the RSA numbers are fixed-point numbers with the decimal point to
+ the left of the most significant bit. This approach helps make it clear what is happening with
+ the MSb of the values. The two RSA primes have to be large enough so that their product will be a
+ number with the necessary number of significant bits. For example, we want to be able to multiply
+ two 1024-bit numbers to produce a number with 2048 significant bits. If we accept any 1024-bit
+ prime that has its MSb set, then it is possible to produce a product that does not have the MSb
+ SET. For example, if we use tiny keys of 16 bits and have two 8-bit primes of 0x80, then the
+ public key would be 0x4000 which is only 15-bits. So, what we need to do is made sure that each
+ of the primes is large enough so that the product of the primes is twice as large as each
+ prime. A little arithmetic will show that the only way to do this is to make sure that each of
+ the primes is no less than root(2)/2. That's what this functions does. This function adjusts the
+ candidate prime so that it is odd and >= root(2)/2. This allows the product of these two numbers
+ to be .5, which, in fixed point notation means that the most significant bit is 1. For this
+ routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 which is, in fixed point,
+ 0.7071075439453125 or an error of 0.000108%. Just setting the upper two bits would give a value >
+ 0.75 which is an error of > 6%. Given the amount of time all the other computations take,
+ reducing the error is not much of a cost, but it isn't totally required either. */
+/* This function can be replaced with a function that just sets the two most significant bits of
+ each prime candidate without introducing any computational issues. */
+
+static void
+RsaAdjustPrimeCandidate_New(
+ bigNum prime
+ )
+{
+ UINT32 msw;
+ UINT32 adjusted;
+
+ // If the radix is 32, the compiler should turn this into a simple assignment
+ msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0);
+ // Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0
+ adjusted = (msw >> 16) * 0x4AFB;
+ adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16;
+ adjusted += 0xB5050000UL;
+#if RADIX_BITS == 64
+ // Save the low-order 32 bits
+ prime->d[prime->size - 1] &= 0xFFFFFFFFUL;
+ // replace the upper 32-bits
+ prime->d[prime->size -1] |= ((crypt_uword_t)adjusted << 32);
+#else
+ prime->d[prime->size - 1] = (crypt_uword_t)adjusted;
+#endif
+ // make sure the number is odd
+ prime->d[0] |= 1;
+}
+
+
+LIB_EXPORT void
+RsaAdjustPrimeCandidate(
+ bigNum prime,
+ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added
+ )
+{
+ switch (seedCompatLevel) {
+ case SEED_COMPAT_LEVEL_ORIGINAL:
+ RsaAdjustPrimeCandidate_PreRev155(prime);
+ break;
+ case SEED_COMPAT_LEVEL_LAST:
+ /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */
+ RsaAdjustPrimeCandidate_New(prime);
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+}
+/* 10.2.14.1.8 BnGeneratePrimeForRSA() */
+/* Function to generate a prime of the desired size with the proper attributes for an RSA prime. */
+
+TPM_RC
+BnGeneratePrimeForRSA(
+ bigNum prime, // IN/OUT: points to the BN that will get the
+ // random value
+ UINT32 bits, // IN: number of bits to get
+ UINT32 exponent, // IN: the exponent
+ RAND_STATE *rand // IN: the random state
+ )
+{
+ BOOL found = FALSE;
+ //
+ // Make sure that the prime is large enough
+ pAssert(prime->allocated >= BITS_TO_CRYPT_WORDS(bits));
+ // Only try to handle specific sizes of keys in order to save overhead
+ pAssert((bits % 32) == 0);
+
+ prime->size = BITS_TO_CRYPT_WORDS(bits);
+
+ while(!found)
+ {
+ // The change below is to make sure that all keys that are generated from the same
+ // seed value will be the same regardless of the endianness or word size of the CPU.
+ // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old
+ // if(g_inFailureMode) // old
+ // libtpms changed begin
+ switch (DRBG_GetSeedCompatLevel(rand)) {
+ case SEED_COMPAT_LEVEL_ORIGINAL:
+ DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));
+ if (g_inFailureMode)
+ return TPM_RC_FAILURE;
+ break;
+ case SEED_COMPAT_LEVEL_LAST:
+ /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */
+ if(!BnGetRandomBits(prime, bits, rand)) // new
+ return TPM_RC_FAILURE;
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+ RsaAdjustPrimeCandidate(prime, DRBG_GetSeedCompatLevel(rand));
+ // libtpms changed end
+ found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+#endif // TPM_ALG_RSA
diff --git a/src/tpm2/crypto/openssl/CryptPrimeSieve.c b/src/tpm2/crypto/openssl/CryptPrimeSieve.c
new file mode 100644
index 0000000..8c4e52b
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptPrimeSieve.c
@@ -0,0 +1,554 @@
+/********************************************************************************/
+/* */
+/* CryptPrimeSieve */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptPrimeSieve.c 1519 2019-11-15 20:43:51Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+/* 10.2.17 CryptPrimeSieve.c */
+/* 10.2.17.1 Includes and defines */
+#include "Tpm.h"
+#if RSA_KEY_SIEVE
+#include "CryptPrimeSieve_fp.h"
+/* This determines the number of bits in the largest sieve field. */
+#define MAX_FIELD_SIZE 2048
+extern const uint32_t s_LastPrimeInTable;
+extern const uint32_t s_PrimeTableSize;
+extern const uint32_t s_PrimesInTable;
+extern const unsigned char s_PrimeTable[];
+/* This table is set of prime markers. Each entry is the prime value for the ((n + 1) * 1024)
+ prime. That is, the entry in s_PrimeMarkers[1] is the value for the 2,048th prime. This is used
+ in the PrimeSieve() to adjust the limit for the prime search. When processing smaller prime
+ candidates, fewer primes are checked directly before going to Miller-Rabin. As the prime grows,
+ it is worth spending more time eliminating primes as, a) the density is lower, and b) the cost of
+ Miller-Rabin is higher. */
+const uint32_t s_PrimeMarkersCount = 6;
+const uint32_t s_PrimeMarkers[] = {
+ 8167, 17881, 28183, 38891, 49871, 60961 };
+uint32_t primeLimit;
+
+/* 10.2.17.1.1 RsaAdjustPrimeLimit() */
+/* This used during the sieve process. The iterator for getting the next prime (RsaNextPrime()) will
+ return primes until it hits the limit (primeLimit) set up by this function. This causes the sieve
+ process to stop when an appropriate number of primes have been sieved. */
+
+void
+RsaAdjustPrimeLimit(
+ uint32_t requestedPrimes
+ )
+{
+ if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable)
+ requestedPrimes = s_PrimesInTable;
+ requestedPrimes = (requestedPrimes - 1) / 1024;
+ if(requestedPrimes < s_PrimeMarkersCount)
+ primeLimit = s_PrimeMarkers[requestedPrimes];
+ else
+ primeLimit = s_LastPrimeInTable - 2; // libtpms: Fix for 3072 bit keys to avoid mark=5
+ primeLimit >>= 1;
+}
+
+/* 10.2.17.1.2 RsaNextPrime() */
+/* This the iterator used during the sieve process. The input is the last prime returned (or any
+ starting point) and the output is the next higher prime. The function returns 0 when the
+ primeLimit is reached. */
+uint32_t
+RsaNextPrime(
+ uint32_t lastPrime
+ )
+{
+ if(lastPrime == 0)
+ return 0;
+ lastPrime >>= 1;
+ for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++)
+ {
+ if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1)
+ return ((lastPrime << 1) + 1);
+ }
+ return 0;
+}
+/* This table contains a previously sieved table. It has the bits for 3, 5, and 7 removed. Because
+ of the factors, it needs to be aligned to 105 and has a repeat of 105. */
+const BYTE seedValues[] = {
+ 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c,
+ 0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96,
+ 0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99,
+ 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69,
+ 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6,
+ 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb,
+ 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c,
+ 0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34,
+ 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b,
+ 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45,
+ 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6,
+ 0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2,
+ 0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29,
+ 0xd1};
+#define USE_NIBBLE
+#ifndef USE_NIBBLE
+static const BYTE bitsInByte[256] = {
+ 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08
+};
+#define BitsInByte(x) bitsInByte[(unsigned char)x]
+#else
+const BYTE bitsInNibble[16] = {
+ 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04};
+#define BitsInByte(x) \
+ (bitsInNibble[(unsigned char)(x) & 0xf] \
+ + bitsInNibble[((unsigned char)(x) >> 4) & 0xf])
+#endif
+
+/* 10.2.17.1.3 BitsInArry() */
+/* This function counts the number of bits set in an array of bytes. */
+static int
+BitsInArray(
+ const unsigned char *a, // IN: A pointer to an array of bytes
+ unsigned int aSize // IN: the number of bytes to sum
+ )
+{
+ int j = 0;
+ for(; aSize; a++, aSize--)
+ j += BitsInByte(*a);
+ return j;
+}
+
+/* 10.2.17.1.4 FindNthSetBit() */
+/* This function finds the nth SET bit in a bit array. The n parameter is between 1 and the number
+ of bits in the array (always a multiple of 8). If called when the array does not have n bits set,
+ it will return -1 */
+/* Return Values Meaning */
+/* <0 no bit is set or no bit with the requested number is set */
+/* >=0 the number of the bit in the array that is the nth set */
+int
+FindNthSetBit(
+ const UINT16 aSize, // IN: the size of the array to check
+ const BYTE *a, // IN: the array to check
+ const UINT32 n // IN, the number of the SET bit
+ )
+{
+ UINT16 i;
+ int retValue;
+ UINT32 sum = 0;
+ BYTE sel;
+ //find the bit
+ for(i = 0; (i < (int)aSize) && (sum < n); i++)
+ sum += BitsInByte(a[i]);
+ i--;
+ // The chosen bit is in the byte that was just accessed
+ // Compute the offset to the start of that byte
+ retValue = i * 8 - 1;
+ sel = a[i];
+ // Subtract the bits in the last byte added.
+ sum -= BitsInByte(sel);
+ // Now process the byte, one bit at a time.
+ for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1)
+ sum += (sel & 1) != 0;
+ return (sum == n) ? retValue : -1;
+}
+typedef struct
+{
+ UINT16 prime;
+ UINT16 count;
+} SIEVE_MARKS;
+const SIEVE_MARKS sieveMarks[5] = {
+ {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}};
+
+/* 10.2.17.1.5 PrimeSieve() */
+/* This function does a prime sieve over the input field which has as its starting address the value
+ in bnN. Since this initializes the Sieve using a precomputed field with the bits associated with
+ 3, 5 and 7 already turned off, the value of pnN may need to be adjusted by a few counts to allow
+ the precomputed field to be used without modification. */
+/* To get better performance, one could address the issue of developing the composite numbers. When
+ the size of the prime gets large, the time for doing the divisions goes up, noticeably. It could
+ be better to develop larger composite numbers even if they need to be bigNum's themselves. The
+ object would be to reduce the number of times that the large prime is divided into a few large
+ divides and then use smaller divides to get to the final 16 bit (or smaller) remainders. */
+UINT32
+PrimeSieve(
+ bigNum bnN, // IN/OUT: number to sieve
+ UINT32 fieldSize, // IN: size of the field area in bytes
+ BYTE *field // IN: field
+ )
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 fieldBits = fieldSize * 8;
+ UINT32 r;
+ BYTE *pField;
+ INT32 iter;
+ UINT32 adjust;
+ UINT32 mark = 0;
+ UINT32 count = sieveMarks[0].count;
+ UINT32 stop = sieveMarks[0].prime;
+ UINT32 composite;
+ UINT32 pList[8];
+ UINT32 next;
+ pAssert(field != NULL && bnN != NULL);
+ // If the remainder is odd, then subtracting the value will give an even number,
+ // but we want an odd number, so subtract the 105+rem. Otherwise, just subtract
+ // the even remainder.
+ adjust = (UINT32)BnModWord(bnN, 105);
+ if(adjust & 1)
+ adjust += 105;
+ // Adjust the input number so that it points to the first number in a
+ // aligned field.
+ BnSubWord(bnN, bnN, adjust);
+ // pAssert(BnModWord(bnN, 105) == 0);
+ pField = field;
+ for(i = fieldSize; i >= sizeof(seedValues);
+ pField += sizeof(seedValues), i -= sizeof(seedValues))
+ {
+ memcpy(pField, seedValues, sizeof(seedValues));
+ }
+ if(i != 0)
+ memcpy(pField, seedValues, i);
+ // Cycle through the primes, clearing bits
+ // Have already done 3, 5, and 7
+ iter = 7;
+#define NEXT_PRIME(iter) (iter = RsaNextPrime(iter))
+ // Get the next N primes where N is determined by the mark in the sieveMarks
+ while((composite = NEXT_PRIME(iter)) != 0)
+ {
+ next = 0;
+ i = count;
+ pList[i--] = composite;
+ for(; i > 0; i--)
+ {
+ next = NEXT_PRIME(iter);
+ pList[i] = next;
+ if(next != 0)
+ composite *= next;
+ }
+ // Get the remainder when dividing the base field address
+ // by the composite
+ composite = (UINT32)BnModWord(bnN, composite);
+ // 'composite' is divisible by the composite components. for each of the
+ // composite components, divide 'composite'. That remainder (r) is used to
+ // pick a starting point for clearing the array. The stride is equal to the
+ // composite component. Note, the field only contains odd numbers. If the
+ // field were expanded to contain all numbers, then half of the bits would
+ // have already been cleared. We can save the trouble of clearing them a
+ // second time by having a stride of 2*next. Or we can take all of the even
+ // numbers out of the field and use a stride of 'next'
+ for(i = count; i > 0; i--)
+ {
+ next = pList[i];
+ if(next == 0)
+ goto done;
+ r = composite % next;
+ // these computations deal with the fact that we have picked a field-sized
+ // range that is aligned to a 105 count boundary. The problem is, this field
+ // only contains odd numbers. If we take our prime guess and walk through all
+ // the numbers using that prime as the 'stride', then every other 'stride' is
+ // going to be an even number. So, we are actually counting by 2 * the stride
+ // We want the count to start on an odd number at the start of our field. That
+ // is, we want to assume that we have counted up to the edge of the field by
+ // the 'stride' and now we are going to start flipping bits in the field as we
+ // continue to count up by 'stride'. If we take the base of our field and
+ // divide by the stride, we find out how much we find out how short the last
+ // count was from reaching the edge of the bit field. Say we get a quotient of
+ // 3 and remainder of 1. This means that after 3 strides, we are 1 short of
+ // the start of the field and the next stride will either land within the
+ // field or step completely over it. The confounding factor is that our field
+ // only contains odd numbers and our stride is actually 2 * stride. If the
+ // quoitent is even, then that means that when we add 2 * stride, we are going
+ // to hit another even number. So, we have to know if we need to back off
+ // by 1 stride before we start counting by 2 * stride.
+ // We can tell from the remainder whether we are on an even or odd
+ // stride when we hit the beginning of the table. If we are on an odd stride
+ // (r & 1), we would start half a stride in (next - r)/2. If we are on an
+ // even stride, we need 0.5 strides (next - r/2) because the table only has
+ // odd numbers. If the remainder happens to be zero, then the start of the
+ // table is on stride so no adjustment is necessary.
+
+ if(r & 1) j = (next - r) / 2;
+ else if(r == 0) j = 0;
+ else j = next - (r / 2);
+ for(; j < fieldBits; j += next)
+ ClearBit(j, field, fieldSize);
+ }
+ if(next >= stop)
+ {
+ mark++;
+ count = sieveMarks[mark].count;
+ stop = sieveMarks[mark].prime;
+ }
+ }
+ done:
+ INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]);
+ i = BitsInArray(field, fieldSize);
+ INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i);
+ INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0));
+ return i;
+}
+#ifdef SIEVE_DEBUG
+static uint32_t fieldSize = 210;
+
+/* 10.2.17.1.6 SetFieldSize() */
+/* Function to set the field size used for prime generation. Used for tuning. */
+uint32_t
+SetFieldSize(
+ uint32_t newFieldSize
+ )
+{
+ if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE)
+ fieldSize = MAX_FIELD_SIZE;
+ else
+ fieldSize = newFieldSize;
+ return fieldSize;
+}
+#endif // SIEVE_DEBUG
+
+/* 10.2.17.1.7 PrimeSelectWithSieve() */
+/* This function will sieve the field around the input prime candidate. If the sieve field is not
+ empty, one of the one bits in the field is chosen for testing with Miller-Rabin. If the value is
+ prime, pnP is updated with this value and the function returns success. If this value is not
+ prime, another pseudo-random candidate is chosen and tested. This process repeats until all
+ values in the field have been checked. If all bits in the field have been checked and none is
+ prime, the function returns FALSE and a new random value needs to be chosen. */
+/* Error Returns Meaning */
+/* TPM_RC_FAILURE TPM in failure mode, probably due to entropy source */
+/* TPM_RC_SUCCESS candidate is probably prime */
+/* TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative in the field */
+LIB_EXPORT TPM_RC
+PrimeSelectWithSieve(
+ bigNum candidate, // IN/OUT: The candidate to filter
+ UINT32 e, // IN: the exponent
+ RAND_STATE *rand // IN: the random number generator state
+ )
+{
+ BYTE field[MAX_FIELD_SIZE];
+ UINT32 first;
+ UINT32 ones;
+ INT32 chosen;
+ BN_PRIME(test);
+ UINT32 modE;
+#ifndef SIEVE_DEBUG
+ UINT32 fieldSize = MAX_FIELD_SIZE;
+#endif
+ UINT32 primeSize;
+ //
+ // Adjust the field size and prime table list to fit the size of the prime
+ // being tested. This is done to try to optimize the trade-off between the
+ // dividing done for sieving and the time for Miller-Rabin. When the size
+ // of the prime is large, the cost of Miller-Rabin is fairly high, as is the
+ // cost of the sieving. However, the time for Miller-Rabin goes up considerably
+ // faster than the cost of dividing by a number of primes.
+ primeSize = BnSizeInBits(candidate);
+
+ if(primeSize <= 512)
+ {
+ RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes
+ }
+ else if(primeSize <= 1024)
+ {
+ RsaAdjustPrimeLimit(4096); // Use just the first 4K primes
+ }
+ else
+ {
+ RsaAdjustPrimeLimit(0); // Use all available
+ }
+
+ // Save the low-order word to use as a search generator and make sure that
+ // it has some interesting range to it
+ first = (UINT32)(candidate->d[0] | 0x80000000);
+
+ // Sieve the field
+ ones = PrimeSieve(candidate, fieldSize, field);
+ pAssert(ones > 0 && ones < (fieldSize * 8));
+ for(; ones > 0; ones--)
+ {
+ // Decide which bit to look at and find its offset
+ chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1));
+
+ if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8)))
+ FAIL(FATAL_ERROR_INTERNAL);
+
+ // Set this as the trial prime
+ BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2));
+
+ // The exponent might not have been one of the tested primes so
+ // make sure that it isn't divisible and make sure that 0 != (p-1) mod e
+ // Note: This is the same as 1 != p mod e
+ modE = (UINT32)BnModWord(test, e);
+ if((modE != 0) && (modE != 1) && MillerRabin(test, rand))
+ {
+ BnCopy(candidate, test);
+ return TPM_RC_SUCCESS;
+ }
+ // Clear the bit just tested
+ ClearBit(chosen, field, fieldSize);
+ }
+ // Ran out of bits and couldn't find a prime in this field
+ INSTRUMENT_INC(noPrimeFields[PrimeIndex]);
+ return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT);
+}
+
+#if RSA_INSTRUMENT
+static char a[256];
+char *
+PrintTuple(
+ UINT32 *i
+ )
+{
+ sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]);
+ return a;
+}
+#define CLEAR_VALUE(x) memset(x, 0, sizeof(x))
+
+void
+RsaSimulationEnd(
+ void
+ )
+{
+ int i;
+ UINT32 averages[3];
+ UINT32 nonFirst = 0;
+ if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0)
+ {
+ printf("Primes generated = %s\n", PrintTuple(PrimeCounts));
+ printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved));
+ printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields));
+ printf("Primes checked with Miller-Rabin = %s\n",
+ PrintTuple(MillerRabinTrials));
+ for(i = 0; i < 3; i++)
+ averages[i] = (totalFieldsSieved[i]
+ != 0 ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i]
+ : 0);
+ printf("Average candidates in field %s\n", PrintTuple(averages));
+ for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0]));
+ i++)
+ nonFirst += failedAtIteration[i];
+ printf("Miller-Rabin failures not in first round = %d\n", nonFirst);
+ }
+ CLEAR_VALUE(PrimeCounts);
+ CLEAR_VALUE(totalFieldsSieved);
+ CLEAR_VALUE(noPrimeFields);
+ CLEAR_VALUE(MillerRabinTrials);
+ CLEAR_VALUE(bitsInFieldAfterSieve);
+}
+void
+GetSieveStats(
+ uint32_t *trials,
+ uint32_t *emptyFields,
+ uint32_t *averageBits
+ )
+{
+ uint32_t totalBits;
+ uint32_t fields;
+ *trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2];
+ *emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2];
+ fields = totalFieldsSieved[0] + totalFieldsSieved[1]
+ + totalFieldsSieved[2];
+ totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1]
+ + bitsInFieldAfterSieve[2];
+ if(fields != 0)
+ *averageBits = totalBits / fields;
+ else
+ *averageBits = 0;
+ CLEAR_VALUE(PrimeCounts);
+ CLEAR_VALUE(totalFieldsSieved);
+ CLEAR_VALUE(noPrimeFields);
+ CLEAR_VALUE(MillerRabinTrials);
+ CLEAR_VALUE(bitsInFieldAfterSieve);
+}
+#endif
+#endif // RSA_KEY_SIEVE
+#if !RSA_INSTRUMENT
+//*** RsaSimulationEnd()
+// Stub for call when not doing instrumentation.
+#if 0 // libtpms added
+void
+RsaSimulationEnd(
+ void
+ )
+{
+ return;
+}
+#endif // libtpms added
+#endif
diff --git a/src/tpm2/crypto/openssl/CryptRand.c b/src/tpm2/crypto/openssl/CryptRand.c
new file mode 100644
index 0000000..5bf0643
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptRand.c
@@ -0,0 +1,881 @@
+/********************************************************************************/
+/* */
+/* DRBG with a behavior according to SP800-90A */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRand.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+#include "Tpm.h"
+#include "PRNG_TestVectors.h"
+const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY};
+const BYTE DRBG_NistTestVector_GeneratedInterm[] =
+ {DRBG_TEST_GENERATED_INTERM};
+const BYTE DRBG_NistTestVector_EntropyReseed[] =
+ {DRBG_TEST_RESEED_ENTROPY};
+const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED};
+
+/* 10.2.16.2.2 Derivation Function Defines and Structures */
+#define DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1)
+#if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256
+# error "CryptRand.c only written for AES with 128- or 256-bit keys."
+#endif
+
+typedef struct
+{
+ DRBG_KEY_SCHEDULE keySchedule;
+ DRBG_IV iv[DF_COUNT];
+ DRBG_IV out1;
+ DRBG_IV buf;
+ int contents;
+} DF_STATE, *PDF_STATE;
+/* 10.2.16.2.3 DfCompute() */
+/* This function does the incremental update of the derivation function state. It encrypts the iv
+ value and XOR's the results into each of the blocks of the output. This is equivalent to
+ processing all of input data for each output block. */
+static void
+DfCompute(
+ PDF_STATE dfState
+ )
+{
+ int i;
+ int iv;
+ crypt_uword_t *pIv;
+ crypt_uword_t temp[DRBG_IV_SIZE_WORDS] = {0};
+ //
+ for(iv = 0; iv < DF_COUNT; iv++)
+ {
+ pIv = (crypt_uword_t *)&dfState->iv[iv].words[0];
+ for(i = 0; i < DRBG_IV_SIZE_WORDS; i++)
+ {
+ temp[i] ^= pIv[i] ^ dfState->buf.words[i];
+ }
+ DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv);
+ }
+ for(i = 0; i < DRBG_IV_SIZE_WORDS; i++)
+ dfState->buf.words[i] = 0;
+ dfState->contents = 0;
+}
+/* 10.2.16.2.4 DfStart() */
+/* This initializes the output blocks with an encrypted counter value and initializes the key
+ schedule. */
+static void
+DfStart(
+ PDF_STATE dfState,
+ uint32_t inputLength
+ )
+{
+ BYTE init[8];
+ int i;
+ UINT32 drbgSeedSize = sizeof(DRBG_SEED);
+ const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+#if DRBG_KEY_SIZE_BYTES > 16
+ ,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+#endif
+ };
+ memset(dfState, 0, sizeof(DF_STATE));
+ DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule);
+ // Create the first chaining values
+ for(i = 0; i < DF_COUNT; i++)
+ ((BYTE *)&dfState->iv[i])[3] = (BYTE)i;
+ DfCompute(dfState);
+ // initialize the first 64 bits of the IV in a way that doesn't depend
+ // on the size of the words used.
+ UINT32_TO_BYTE_ARRAY(inputLength, init);
+ UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]);
+ memcpy(&dfState->iv[0], init, 8);
+ dfState->contents = 4;
+}
+/* 10.2.16.2.5 DfUpdate() */
+/* This updates the state with the input data. A byte at a time is moved into the state buffer until
+ it is full and then that block is encrypted by DfCompute(). */
+static void
+DfUpdate(
+ PDF_STATE dfState,
+ int size,
+ const BYTE *data
+ )
+{
+ while(size > 0)
+ {
+ int toFill = DRBG_IV_SIZE_BYTES - dfState->contents;
+ if(size < toFill)
+ toFill = size;
+ // Copy as many bytes as there are or until the state buffer is full
+ memcpy(&dfState->buf.bytes[dfState->contents], data, toFill);
+ // Reduce the size left by the amount copied
+ size -= toFill;
+ // Advance the data pointer by the amount copied
+ data += toFill;
+ // increase the buffer contents count by the amount copied
+ dfState->contents += toFill;
+ pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES);
+ // If we have a full buffer, do a computation pass.
+ if(dfState->contents == DRBG_IV_SIZE_BYTES)
+ DfCompute(dfState);
+ }
+}
+/* 10.2.16.2.6 DfEnd() */
+/* This function is called to get the result of the derivation function computation. If the buffer
+ is not full, it is padded with zeros. The output buffer is structured to be the same as a
+ DRBG_SEED value so that the function can return a pointer to the DRBG_SEED value in the DF_STATE
+ structure. */
+static DRBG_SEED *
+DfEnd(
+ PDF_STATE dfState
+ )
+{
+ // Since DfCompute is always called when a buffer is full, there is always
+ // space in the buffer for the terminator
+ dfState->buf.bytes[dfState->contents++] = 0x80;
+ // If the buffer is not full, pad with zeros
+ while(dfState->contents < DRBG_IV_SIZE_BYTES)
+ dfState->buf.bytes[dfState->contents++] = 0;
+ // Do a final state update
+ DfCompute(dfState);
+ return (DRBG_SEED *)&dfState->iv;
+}
+/* 10.2.16.2.7 DfBuffer() */
+/* Function to take an input buffer and do the derivation function to produce a DRBG_SEED value that
+ can be used in DRBG_Reseed(); */
+static DRBG_SEED *
+DfBuffer(
+ DRBG_SEED *output, // OUT: receives the result
+ int size, // IN: size of the buffer to add
+ BYTE *buf // IN: address of the buffer
+ )
+{
+ DF_STATE dfState;
+ if(size == 0 || buf == NULL)
+ return NULL;
+ // Initialize the derivation function
+ DfStart(&dfState, size);
+ DfUpdate(&dfState, size, buf);
+ DfEnd(&dfState);
+ memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED));
+ return output;
+}
+/* 10.2.16.2.8 DRBG_GetEntropy() */
+/* Even though this implementation never fails, it may get blocked indefinitely long in the call to
+ get entropy from the platform (DRBG_GetEntropy32()). This function is only used during
+ instantiation of the DRBG for manufacturing and on each start-up after an non-orderly
+ shutdown. */
+/* Return Values Meaning */
+/* TRUE Requested entropy returned */
+/* FALSE Entropy Failure */
+BOOL
+DRBG_GetEntropy(
+ UINT32 requiredEntropy, // IN: requested number of bytes of full
+ // entropy
+ BYTE *entropy // OUT: buffer to return collected entropy
+ )
+{
+#if !USE_DEBUG_RNG
+ UINT32 obtainedEntropy;
+ INT32 returnedEntropy;
+ // If in debug mode, always use the self-test values for initialization
+ if(IsSelfTest())
+ {
+#endif
+ // If doing simulated DRBG, then check to see if the
+ // entropyFailure condition is being tested
+ if(!IsEntropyBad())/* This function increments the IV value by 1. It is used by EncryptDRBG(). */
+ {
+ // In self-test, the caller should be asking for exactly the seed
+ // size of entropy.
+ pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy));
+ memcpy(entropy, DRBG_NistTestVector_Entropy,
+ sizeof(DRBG_NistTestVector_Entropy));
+ }
+#if !USE_DEBUG_RNG
+ }
+ else if(!IsEntropyBad())
+ {
+ // Collect entropy
+ // Note: In debug mode, the only "entropy" value ever returned
+ // is the value of the self-test vector.
+ for(returnedEntropy = 1, obtainedEntropy = 0;
+ obtainedEntropy < requiredEntropy && !IsEntropyBad();
+ obtainedEntropy += returnedEntropy)
+ {
+ returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy],
+ requiredEntropy - obtainedEntropy);
+ if(returnedEntropy <= 0)
+ SetEntropyBad();
+ }
+ }
+#endif
+ return !IsEntropyBad();
+}
+
+void
+IncrementIv(
+ DRBG_IV *iv
+ )
+{
+ BYTE *ivP = ((BYTE *)iv) + DRBG_IV_SIZE_BYTES;
+ while((--ivP >= (BYTE *)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0));
+}
+/* 10.2.16.2.10 EncryptDRBG() */
+/* This does the encryption operation for the DRBG. It will encrypt the input state counter (IV)
+ using the state key. Into the output buffer for as many times as it takes to generate the
+ required number of bytes. */
+static BOOL
+EncryptDRBG(
+ BYTE *dOut,
+ UINT32 dOutBytes,
+ DRBG_KEY_SCHEDULE *keySchedule,
+ DRBG_IV *iv,
+ UINT32 *lastValue // Points to the last output value
+ )
+{
+#if FIPS_COMPLIANT
+ // For FIPS compliance, the DRBG has to do a continuous self-test to make sure that
+ // no two consecutive values are the same. This overhead is not incurred if the TPM
+ // is not required to be FIPS compliant
+ //
+ UINT32 temp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)];
+ int i;
+ BYTE *p;
+ for(; dOutBytes > 0;)
+ {
+ // Increment the IV before each encryption (this is what makes this
+ // different from normal counter-mode encryption
+ IncrementIv(iv);
+ DRBG_ENCRYPT(keySchedule, iv, temp);
+ // Expect a 16 byte block
+#if DRBG_IV_SIZE_BITS != 128
+#error "Unsuppored IV size in DRBG"
+#endif
+ if((lastValue[0] == temp[0])
+ && (lastValue[1] == temp[1])
+ && (lastValue[2] == temp[2])
+ && (lastValue[3] == temp[3])
+ )
+ {
+ LOG_FAILURE(FATAL_ERROR_ENTROPY);
+ return FALSE;
+ }
+ lastValue[0] = temp[0];
+ lastValue[1] = temp[1];
+ lastValue[2] = temp[2];
+ lastValue[3] = temp[3];
+ i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES);
+ dOutBytes -= i;
+ for(p = (BYTE *)temp; i > 0; i--)
+ *dOut++ = *p++;
+ }
+#else // version without continuous self-test
+ NOT_REFERENCED(lastValue);
+ for(; dOutBytes >= DRBG_IV_SIZE_BYTES;
+ dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES)
+ {
+ // Increment the IV
+ IncrementIv(iv);
+ DRBG_ENCRYPT(keySchedule, iv, dOut);
+ }
+ // If there is a partial, generate into a block-sized
+ // temp buffer and copy to the output.
+ if(dOutBytes != 0)
+ {
+ BYTE temp[DRBG_IV_SIZE_BYTES];
+ // Increment the IV
+ IncrementIv(iv);
+ DRBG_ENCRYPT(keySchedule, iv, temp);
+ memcpy(dOut, temp, dOutBytes);
+ }
+#endif
+ return TRUE;
+}
+/* 10.2.16.2.11 DRBG_Update() */
+/* This function performs the state update function. According to SP800-90A, a temp value is created
+ by doing CTR mode encryption of providedData and replacing the key and IV with these values. The
+ one difference is that, with counter mode, the IV is incremented after each block is encrypted
+ and in this operation, the counter is incremented before each block is encrypted. This function
+ implements an optimized version of the algorithm in that it does the update of the
+ drbgState->seed in place and then providedData is XORed into drbgState->seed to complete the
+ encryption of providedData. This works because the IV is the last thing that gets encrypted. */
+static BOOL
+DRBG_Update(
+ DRBG_STATE *drbgState, // IN:OUT state to update
+ DRBG_KEY_SCHEDULE *keySchedule, // IN: the key schedule (optional)
+ DRBG_SEED *providedData // IN: additional data
+ )
+{
+ UINT32 i;
+ BYTE *temp = (BYTE *)&drbgState->seed;
+ DRBG_KEY *key = pDRBG_KEY(&drbgState->seed);
+ DRBG_IV *iv = pDRBG_IV(&drbgState->seed);
+ DRBG_KEY_SCHEDULE localKeySchedule;
+ memset(&localKeySchedule, 0, sizeof(localKeySchedule)); /* libtpms added: coverity */
+ //
+ pAssert(drbgState->magic == DRBG_MAGIC);
+ // If an key schedule was not provided, make one
+ if(keySchedule == NULL)
+ {
+ if(DRBG_ENCRYPT_SETUP((BYTE *)key,
+ DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0)
+ {
+ LOG_FAILURE(FATAL_ERROR_INTERNAL);
+ return FALSE;
+ }
+ keySchedule = &localKeySchedule;
+ }
+ // Encrypt the temp value
+ EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv,
+ drbgState->lastValue);
+ if(providedData != NULL)
+ {
+ BYTE *pP = (BYTE *)providedData;
+ for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--)
+ *temp++ ^= *pP++;
+ }
+ // Since temp points to the input key and IV, we are done and
+ // don't need to copy the resulting 'temp' to drbgState->seed
+ return TRUE;
+}
+/* 10.2.16.2.12 DRBG_Reseed() */
+/* This function is used when reseeding of the DRBG is required. If entropy is provided, it is used
+ in lieu of using hardware entropy. */
+/* NOTE: the provided entropy must be the required size. */
+/* Return Values Meaning */
+/* TRUE reseed succeeded */
+/* FALSE reseed failed, probably due to the entropy generation */
+BOOL
+DRBG_Reseed(
+ DRBG_STATE *drbgState, // IN: the state to update
+ DRBG_SEED *providedEntropy, // IN: entropy
+ DRBG_SEED *additionalData // IN:
+ )
+{
+ DRBG_SEED seed;
+ pAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC));
+ if(providedEntropy == NULL)
+ {
+ providedEntropy = &seed;
+ if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE *)providedEntropy))
+ return FALSE;
+ }
+ if(additionalData != NULL)
+ {
+ unsigned int i;
+ // XOR the provided data into the provided entropy
+ for(i = 0; i < sizeof(DRBG_SEED); i++)
+ ((BYTE *)providedEntropy)[i] ^= ((BYTE *)additionalData)[i];
+ }
+ DRBG_Update(drbgState, NULL, providedEntropy);
+ drbgState->reseedCounter = 1;
+ return TRUE;
+}
+/* 10.2.16.2.13 DRBG_SelfTest() */
+/* This is run when the DRBG is instantiated and at startup */
+/* Return Values Meaning */
+/* FALSE test failed */
+/* TRUE test OK */
+BOOL
+DRBG_SelfTest(
+ void
+ )
+{
+ BYTE buf[sizeof(DRBG_NistTestVector_Generated)];
+ DRBG_SEED seed;
+ UINT32 i;
+ BYTE *p;
+ DRBG_STATE testState;
+ //
+ pAssert(!IsSelfTest());
+ SetSelfTest();
+ SetDrbgTested();
+ // Do an instantiate
+ if(!DRBG_Instantiate(&testState, 0, NULL))
+ return FALSE;
+#if DRBG_DEBUG_PRINT
+ dbgDumpMemBlock(pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES,
+ "Key after Instantiate");
+ dbgDumpMemBlock(pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES,
+ "Value after Instantiate");
+#endif
+ if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
+ return FALSE;
+#if DRBG_DEBUG_PRINT
+ dbgDumpMemBlock(pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,
+ "Key after 1st Generate");
+ dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,
+ "Value after 1st Generate");
+#endif
+ if(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0)
+ return FALSE;
+ memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed));
+ DRBG_Reseed(&testState, &seed, NULL);
+#if DRBG_DEBUG_PRINT
+ dbgDumpMemBlock((BYTE *)pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES,
+ "Key after 2nd Generate");
+ dbgDumpMemBlock((BYTE *)pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES,
+ "Value after 2nd Generate");
+ dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated");
+#endif
+ if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0)
+ return FALSE;
+ if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0)
+ return FALSE;
+ ClearSelfTest();
+ DRBG_Uninstantiate(&testState);
+ for(p = (BYTE *)&testState, i = 0; i < sizeof(DRBG_STATE); i++)
+ {
+ if(*p++)
+ return FALSE;
+ }
+ // Simulate hardware failure to make sure that we get an error when
+ // trying to instantiate
+ SetEntropyBad();
+ if(DRBG_Instantiate(&testState, 0, NULL))
+ return FALSE;
+ ClearEntropyBad();
+ return TRUE;
+}
+/* 10.2.16.3 Public Interface */
+
+/* 10.2.16.3.1 Description */
+/* The functions in this section are the interface to the RNG. These are the functions that are used
+ by TPM.lib. */
+
+/* 10.2.16.3.2 CryptRandomStir() */
+/* This function is used to cause a reseed. A DRBG_SEED amount of entropy is collected from the
+ hardware and then additional data is added. */
+/* Error Returns Meaning */
+/* TPM_RC_NO_RESULT failure of the entropy generator */
+LIB_EXPORT TPM_RC
+CryptRandomStir(
+ UINT16 additionalDataSize,
+ BYTE *additionalData
+ )
+{
+#if !USE_DEBUG_RNG
+ DRBG_SEED tmpBuf;
+ DRBG_SEED dfResult;
+ //
+ // All reseed with outside data starts with a buffer full of entropy
+ if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf))
+ return TPM_RC_NO_RESULT;
+ DRBG_Reseed(&drbgDefault, &tmpBuf,
+ DfBuffer(&dfResult, additionalDataSize, additionalData));
+ drbgDefault.reseedCounter = 1;
+ return TPM_RC_SUCCESS;
+#else
+ // If doing debug, use the input data as the initial setting for the RNG state
+ // so that the test can be reset at any time.
+ // Note: If this is called with a data size of 0 or less, nothing happens. The
+ // presumption is that, in a debug environment, the caller will have specific
+ // values for initialization, so this check is just a simple way to prevent
+ // inadvertent programming errors from screwing things up. This doesn't use an
+ // pAssert() because the non-debug version of this function will accept these
+ // parameters as meaning that there is no additionalData and only hardware
+ // entropy is used.
+ if((additionalDataSize > 0) && (additionalData != NULL))
+ {
+ memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes));
+ memcpy(drbgDefault.seed.bytes, additionalData,
+ MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes)));
+ }
+ drbgDefault.reseedCounter = 1;
+ return TPM_RC_SUCCESS;
+#endif
+}
+/* 10.2.16.3.3 CryptRandomGenerate() */
+/* Generate a randomSize number or random bytes. */
+LIB_EXPORT UINT16
+CryptRandomGenerate(
+ UINT16 randomSize,
+ BYTE *buffer
+ )
+{
+ return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, randomSize);
+}
+/* 10.2.16.3.4 DRBG_InstantiateSeededKdf() */
+/* Function used to instantiate a KDF-based RNG. This is used for derivations. This function always
+ returns TRUE. */
+LIB_EXPORT BOOL
+DRBG_InstantiateSeededKdf(
+ KDF_STATE *state, // OUT: buffer to hold the state
+ TPM_ALG_ID hashAlg, // IN: hash algorithm
+ TPM_ALG_ID kdf, // IN: the KDF to use
+ TPM2B *seed, // IN: the seed to use
+ const TPM2B *label, // IN: a label for the generation process.
+ TPM2B *context, // IN: the context value
+ UINT32 limit // IN: Maximum number of bits from the KDF
+ )
+{
+ state->magic = KDF_MAGIC;
+ state->limit = limit;
+ state->seed = seed;
+ state->hash = hashAlg;
+ state->kdf = kdf;
+ state->label = label;
+ state->context = context;
+ state->digestSize = CryptHashGetDigestSize(hashAlg);
+ state->counter = 0;
+ state->residual.t.size = 0;
+ return TRUE;
+}
+/* 10.2.16.3.5 DRBG_AdditionalData() */
+/* Function to reseed the DRBG with additional entropy. This is normally called before computing the
+ protection value of a primary key in the Endorsement hierarchy. */
+LIB_EXPORT void
+DRBG_AdditionalData(
+ DRBG_STATE *drbgState, // IN:OUT state to update
+ TPM2B *additionalData // IN: value to incorporate
+ )
+{
+ DRBG_SEED dfResult;
+ if(drbgState->magic == DRBG_MAGIC)
+ {
+ DfBuffer(&dfResult, additionalData->size, additionalData->buffer);
+ DRBG_Reseed(drbgState, &dfResult, NULL);
+ }
+}
+/* 10.2.16.3.6 DRBG_InstantiateSeeded() */
+/* This function is used to instantiate a random number generator from seed values. The nominal use
+ of this generator is to create sequences of pseudo-random numbers from a seed value. */
+/* Returns
+ TPM_RC_FAILURE DRBG self-test failure
+*/
+LIB_EXPORT TPM_RC
+DRBG_InstantiateSeeded(
+ DRBG_STATE *drbgState, // IN/OUT: buffer to hold the state
+ const TPM2B *seed, // IN: the seed to use
+ const TPM2B *purpose, // IN: a label for the generation process.
+ const TPM2B *name, // IN: name of the object
+ const TPM2B *additional, // IN: additional data
+ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added
+ )
+{
+ DF_STATE dfState;
+ int totalInputSize;
+ // DRBG should have been tested, but...
+ if(!IsDrbgTested() && !DRBG_SelfTest())
+ {
+ LOG_FAILURE(FATAL_ERROR_SELF_TEST);
+ return TPM_RC_FAILURE;
+ }
+ // Initialize the DRBG state
+ memset(drbgState, 0, sizeof(DRBG_STATE));
+ drbgState->magic = DRBG_MAGIC;
+ drbgState->seedCompatLevel = seedCompatLevel; // libtpms added
+ // Size all of the values
+ totalInputSize = (seed != NULL) ? seed->size : 0;
+ totalInputSize += (purpose != NULL) ? purpose->size : 0;
+ totalInputSize += (name != NULL) ? name->size : 0;
+ totalInputSize += (additional != NULL) ? additional->size : 0;
+ // Initialize the derivation
+ DfStart(&dfState, totalInputSize);
+ // Run all the input strings through the derivation function
+ if(seed != NULL)
+ DfUpdate(&dfState, seed->size, seed->buffer);
+ if(purpose != NULL)
+ DfUpdate(&dfState, purpose->size, purpose->buffer);
+ if(name != NULL)
+ DfUpdate(&dfState, name->size, name->buffer);
+ if(additional != NULL)
+ DfUpdate(&dfState, additional->size, additional->buffer);
+ // Used the derivation function output as the "entropy" input. This is not
+ // how it is described in SP800-90A but this is the equivalent function
+ DRBG_Reseed(((DRBG_STATE *)drbgState), DfEnd(&dfState), NULL);
+ return TPM_RC_SUCCESS;
+}
+/* 10.2.16.3.7 CryptRandStartup() */
+/* This function is called when TPM_Startup() is executed. */
+/* TRUE instantiation succeeded */ /* kgold */
+/* FALSE instantiation failed */
+LIB_EXPORT BOOL
+CryptRandStartup(
+ void
+ )
+{
+#if ! _DRBG_STATE_SAVE
+ // If not saved in NV, re-instantiate on each startup
+ return DRBG_Instantiate(&drbgDefault, 0, NULL);
+#else
+ // If the running state is saved in NV, NV has to be loaded before it can
+ // be updated
+ if(go.drbgState.magic == DRBG_MAGIC)
+ return DRBG_Reseed(&go.drbgState, NULL, NULL);
+ else
+ return DRBG_Instantiate(&go.drbgState, 0, NULL);
+#endif
+}
+/* 10.2.16.3.8 CryptRandInit() */
+/* This function is called when _TPM_Init() is being processed */
+LIB_EXPORT BOOL
+CryptRandInit(
+ void
+ )
+{
+#if !USE_DEBUG_RNG
+ _plat__GetEntropy(NULL, 0);
+#endif
+ return DRBG_SelfTest();
+}
+// libtpms added begin
+LIB_EXPORT SEED_COMPAT_LEVEL
+DRBG_GetSeedCompatLevel(
+ RAND_STATE *state
+ )
+{
+ if(state == NULL)
+ {
+ return SEED_COMPAT_LEVEL_LAST;
+ }
+ else if(state->drbg.magic == DRBG_MAGIC)
+ {
+ DRBG_STATE *drbgState = (DRBG_STATE *)state;
+
+ return drbgState->seedCompatLevel;
+ }
+ else
+ {
+ return SEED_COMPAT_LEVEL_LAST;
+ }
+}
+// libtpms added end
+/* 10.2.16.5 DRBG_Generate() */
+/* This function generates a random sequence according SP800-90A. If random is not NULL, then
+ randomSize bytes of random values are generated. If random is NULL or randomSize is zero, then
+ the function returns TRUE without generating any bits or updating the reseed counter. This
+ function returns 0 if a reseed is required. Otherwise, it returns the number of bytes produced
+ which could be less than the number requested if the request is too large.("too large" is
+ implementation dependent.) */
+LIB_EXPORT UINT16
+DRBG_Generate(
+ RAND_STATE *state,
+ BYTE *random, // OUT: buffer to receive the random values
+ UINT16 randomSize // IN: the number of bytes to generate
+ )
+{
+ if(state == NULL)
+ state = (RAND_STATE *)&drbgDefault;
+ if(random == NULL)
+ return 0;
+
+ // If the caller used a KDF state, generate a sequence from the KDF not to
+ // exceed the limit.
+ if(state->kdf.magic == KDF_MAGIC)
+ {
+ KDF_STATE *kdf = (KDF_STATE *)state;
+ UINT32 counter = (UINT32)kdf->counter;
+ INT32 bytesLeft = randomSize;
+
+ // If the number of bytes to be returned would put the generator
+ // over the limit, then return 0
+ if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit)
+ return 0;
+ // Process partial and full blocks until all requested bytes provided
+ while(bytesLeft > 0)
+ {
+ // If there is any residual data in the buffer, copy it to the output
+ // buffer
+ if(kdf->residual.t.size > 0)
+ {
+ INT32 size;
+ //
+ // Don't use more of the residual than will fit or more than are
+ // available
+ size = MIN(kdf->residual.t.size, bytesLeft);
+ // Copy some or all of the residual to the output. The residual is
+ // at the end of the buffer. The residual might be a full buffer.
+ MemoryCopy(random,
+ &kdf->residual.t.buffer
+ [kdf->digestSize - kdf->residual.t.size], size);
+ // Advance the buffer pointer
+ random += size;
+ // Reduce the number of bytes left to get
+ bytesLeft -= size;
+ // And reduce the residual size appropriately
+ kdf->residual.t.size -= (UINT16)size;
+ }
+ else
+ {
+ UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize);
+ //
+ // Get the number of required full blocks
+ if(blocks > 0)
+ {
+ UINT16 size = blocks * kdf->digestSize;
+ // Get some number of full blocks and put them in the return buffer
+ CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL,
+ kdf->limit, random, &counter, blocks);
+ // reduce the size remaining to be moved and advance the pointer
+ bytesLeft -= size;
+ random += size;
+ }
+ else
+ {
+ // Fill the residual buffer with a full block and then loop to
+ // top to get part of it copied to the output.
+ kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed,
+ kdf->label, kdf->context, NULL,
+ kdf->limit,
+ kdf->residual.t.buffer,
+ &counter, 1);
+ }
+ }
+ }
+ kdf->counter = counter;
+ return randomSize;
+ }
+ else if(state->drbg.magic == DRBG_MAGIC)
+ {
+ DRBG_STATE *drbgState = (DRBG_STATE *)state;
+ DRBG_KEY_SCHEDULE keySchedule;
+ DRBG_SEED *seed = &drbgState->seed;
+ memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */
+ if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED)
+ {
+ if(drbgState == &drbgDefault)
+ {
+ DRBG_Reseed(drbgState, NULL, NULL);
+ if(IsEntropyBad() && !IsSelfTest())
+ return 0;
+ }
+ else
+ {
+ // If this is a PRNG then the only way to get
+ // here is if the SW has run away.
+ LOG_FAILURE(FATAL_ERROR_INTERNAL);
+ return 0;
+ }
+ }
+ // if the allowed number of bytes in a request is larger than the
+ // less than the number of bytes that can be requested, then check
+#if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST
+ if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST)
+ randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST;
+#endif
+ // Create encryption schedule
+ if(DRBG_ENCRYPT_SETUP((BYTE *)pDRBG_KEY(seed),
+ DRBG_KEY_SIZE_BITS, &keySchedule) != 0)
+ {
+ LOG_FAILURE(FATAL_ERROR_INTERNAL);
+ return 0;
+ }
+ // Generate the random data
+ EncryptDRBG(random, randomSize, &keySchedule, pDRBG_IV(seed),
+ drbgState->lastValue);
+ // Do a key update
+ DRBG_Update(drbgState, &keySchedule, NULL);
+ // Increment the reseed counter
+ drbgState->reseedCounter += 1;
+ }
+ else
+ {
+ LOG_FAILURE(FATAL_ERROR_INTERNAL);
+ return 0; // libtpms changed from FALSE
+ }
+ return randomSize;
+}
+/* 10.2.16.6 DRBG_Instantiate() */
+/* This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. This is called when a the
+ TPM DRBG is to be instantiated. This is called to instantiate a DRBG used by the TPM for normal
+ operations. */
+/* Return Values Meaning */
+/* TRUE instantiation succeeded */
+/* FALSE instantiation failed */
+LIB_EXPORT BOOL
+DRBG_Instantiate(
+ DRBG_STATE *drbgState, // OUT: the instantiated value
+ UINT16 pSize, // IN: Size of personalization string
+ BYTE *personalization // IN: The personalization string
+ )
+{
+ DRBG_SEED seed;
+ DRBG_SEED dfResult;
+ //
+ pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL));
+ // If the DRBG has not been tested, test when doing an instantiation. Since
+ // Instantiation is called during self test, make sure we don't get stuck in a
+ // loop.
+ if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest())
+ return FALSE;
+ // If doing a self test, DRBG_GetEntropy will return the NIST
+ // test vector value.
+ if(!DRBG_GetEntropy(sizeof(seed), (BYTE *)&seed))
+ return FALSE;
+ // set everything to zero
+ memset(drbgState, 0, sizeof(DRBG_STATE));
+ drbgState->magic = DRBG_MAGIC;
+ // Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what
+ // reseeding does. So, do a reduction on the personalization value (if any)
+ // and do a reseed.
+ DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization));
+ return TRUE;
+}
+/* 10.2.16.7 DRBG_Uninstantiate() */
+/* This is Uninstantiate_function() from [SP 800-90A 9.4]. */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE not a valid state */
+LIB_EXPORT TPM_RC
+DRBG_Uninstantiate(
+ DRBG_STATE *drbgState // IN/OUT: working state to erase
+ )
+{
+ if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC))
+ return TPM_RC_VALUE;
+ memset(drbgState, 0, sizeof(DRBG_STATE));
+ return TPM_RC_SUCCESS;
+}
+
diff --git a/src/tpm2/crypto/openssl/CryptRsa.c b/src/tpm2/crypto/openssl/CryptRsa.c
new file mode 100644
index 0000000..4ed0438
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptRsa.c
@@ -0,0 +1,1634 @@
+/********************************************************************************/
+/* */
+/* Implementation of cryptographic primitives for RSA */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptRsa.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.17 CryptRsa.c */
+/* 10.2.17.1 Introduction */
+/* This file contains implementation of cryptographic primitives for RSA. Vendors may replace the
+ implementation in this file with their own library functions. */
+/* 10.2.17.2 Includes */
+/* Need this define to get the private defines for this function */
+#define CRYPT_RSA_C
+#include "Tpm.h"
+#include "Helpers_fp.h" // libtpms added
+
+#include <openssl/rsa.h> // libtpms added
+
+#if ALG_RSA
+/* 10.2.17.3 Obligatory Initialization Functions */
+/* 10.2.17.3.1 CryptRsaInit() */
+/* Function called at _TPM_Init(). */
+BOOL
+CryptRsaInit(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.17.3.2 CryptRsaStartup() */
+/* Function called at TPM2_Startup() */
+BOOL
+CryptRsaStartup(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.17.4 Internal Functions */
+void
+RsaInitializeExponent(
+ privateExponent_t *pExp
+ )
+{
+#if CRT_FORMAT_RSA == NO
+ BN_INIT(pExp->D);
+#else
+ BN_INIT(pExp->Q);
+ BN_INIT(pExp->dP);
+ BN_INIT(pExp->dQ);
+ BN_INIT(pExp->qInv);
+#endif
+}
+/* 10.2.17.4.1 ComputePrivateExponent() */
+/* This function computes the private exponent from the primes. */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure */
+static BOOL
+ComputePrivateExponent(
+ bigNum P, // IN: first prime (size is 1/2 of bnN)
+ bigNum Q, // IN: second prime (size is 1/2 of bnN)
+ bigNum E, // IN: the public exponent
+ bigNum N, // IN: the public modulus
+ privateExponent_t *pExp // OUT:
+ )
+{
+ BOOL pOK;
+ BOOL qOK;
+#if CRT_FORMAT_RSA == NO
+ BN_RSA(bnPhi);
+ //
+ RsaInitializeExponent(pExp);
+ // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1
+ pOK = BnCopy(bnPhi, N);
+ pOK = pOK && BnSub(bnPhi, bnPhi, P);
+ pOK = pOK && BnSub(bnPhi, bnPhi, Q);
+ pOK = pOK && BnAddWord(bnPhi, bnPhi, 1);
+ // Compute the multiplicative inverse d = 1/e mod Phi
+ pOK = pOK && BnModInverse((bigNum)&pExp->D, E, bnPhi);
+ qOK = pOK;
+#else
+ BN_PRIME(temp);
+ bigNum pT;
+ //
+ NOT_REFERENCED(N);
+ RsaInitializeExponent(pExp);
+ BnCopy((bigNum)&pExp->Q, Q);
+ // make p the larger value so that m2 is always less than p
+ if(BnUnsignedCmp(P, Q) < 0)
+ {
+ pT = P;
+ P = Q;
+ Q = pT;
+ }
+ //dP = (1/e) mod (p-1) = d mod (p-1)
+ pOK = BnSubWord(temp, P, 1);
+ pOK = pOK && BnModInverse((bigNum)&pExp->dP, E, temp);
+ //dQ = (1/e) mod (q-1) = d mod (q-1)
+ qOK = BnSubWord(temp, Q, 1);
+ qOK = qOK && BnModInverse((bigNum)&pExp->dQ, E, temp);
+ // qInv = (1/q) mod p
+ if(pOK && qOK)
+ pOK = qOK = BnModInverse((bigNum)&pExp->qInv, Q, P);
+#endif
+ if(!pOK)
+ BnSetWord(P, 0);
+ if(!qOK)
+ BnSetWord(Q, 0);
+ return pOK && qOK;
+}
+/* 10.2.17.4.2 RsaPrivateKeyOp() */
+/* This function is called to do the exponentiation with the private key. Compile options allow use
+ of the simple (but slow) private exponent, or the more complex but faster CRT method. */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure */
+static BOOL
+RsaPrivateKeyOp(
+ bigNum inOut, // IN/OUT: number to be exponentiated
+ bigNum N, // IN: public modulus (can be NULL if CRT)
+ bigNum P, // IN: one of the primes (can be NULL if not CRT)
+ privateExponent_t *pExp
+ )
+{
+ BOOL OK;
+#if CRT_FORMAT_RSA == NO
+ (P);
+ OK = BnModExp(inOut, inOut, (bigNum)&pExp->D, N);
+#else
+ BN_RSA(M1);
+ BN_RSA(M2);
+ BN_RSA(M);
+ BN_RSA(H);
+ bigNum Q = (bigNum)&pExp->Q;
+ NOT_REFERENCED(N);
+ // Make P the larger prime.
+ // NOTE that when the CRT form of the private key is created, dP will always
+ // be computed using the larger of p and q so the only thing needed here is that
+ // the primes be selected so that they agree with dP.
+ if(BnUnsignedCmp(P, Q) < 0)
+ {
+ bigNum T = P;
+ P = Q;
+ Q = T;
+ }
+ // m1 = cdP mod p
+ OK = BnModExp(M1, inOut, (bigNum)&pExp->dP, P);
+ // m2 = cdQ mod q
+ OK = OK && BnModExp(M2, inOut, (bigNum)&pExp->dQ, Q);
+ // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P
+ // so m2 < P
+ OK = OK && BnSub(H, P, M2);
+ OK = OK && BnAdd(H, H, M1);
+ OK = OK && BnModMult(H, H, (bigNum)&pExp->qInv, P);
+ // m = m2 + h * q
+ OK = OK && BnMult(M, H, Q);
+ OK = OK && BnAdd(inOut, M2, M);
+#endif
+ return OK;
+}
+/* 10.2.17.4.3 RSAEP() */
+/* This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a
+ value (m) with the public exponent (e), modulo the public (n). */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE number to exponentiate is larger than the modulus */
+#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
+static TPM_RC
+RSAEP(
+ TPM2B *dInOut, // IN: size of the encrypted block and the size of
+ // the encrypted value. It must be the size of
+ // the modulus.
+ // OUT: the encrypted data. Will receive the
+ // decrypted value
+ OBJECT *key // IN: the key to use
+ )
+{
+ TPM2B_TYPE(4BYTES, 4);
+ TPM2B_4BYTES(e) = {{4, {(BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 24) & 0xff),
+ (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 16) & 0xff),
+ (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 8) & 0xff),
+ (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT)& 0xff)}}};
+ //
+ if(key->publicArea.parameters.rsaDetail.exponent != 0)
+ UINT32_TO_BYTE_ARRAY(key->publicArea.parameters.rsaDetail.exponent,
+ e.t.buffer);
+ return ModExpB(dInOut->size, dInOut->buffer, dInOut->size, dInOut->buffer,
+ e.t.size, e.t.buffer, key->publicArea.unique.rsa.t.size,
+ key->publicArea.unique.rsa.t.buffer);
+}
+/* 10.2.17.4.4 RSADP() */
+/* This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a
+ value (c) with the private exponent (d), modulo the public modulus (n). The decryption is in
+ place. */
+/* This function also checks the size of the private key. If the size indicates that only a prime
+ value is present, the key is converted to being a private exponent. */
+/* Error Returns Meaning */
+/* TPM_RC_SIZE the value to decrypt is larger than the modulus */
+static TPM_RC
+RSADP(
+ TPM2B *inOut, // IN/OUT: the value to encrypt
+ OBJECT *key // IN: the key
+ )
+{
+ BN_RSA_INITIALIZED(bnM, inOut);
+ BN_RSA_INITIALIZED(bnN, &key->publicArea.unique.rsa);
+ BN_RSA_INITIALIZED(bnP, &key->sensitive.sensitive.rsa);
+ if(BnUnsignedCmp(bnM, bnN) >= 0)
+ return TPM_RC_SIZE;
+ // private key operation requires that private exponent be loaded
+ // During self-test, this might not be the case so load it up if it hasn't
+ // already done
+ // been done
+ if(!key->attributes.privateExp)
+ CryptRsaLoadPrivateExponent(key);
+ if(!RsaPrivateKeyOp(bnM, bnN, bnP, &key->privateExponent))
+ FAIL(FATAL_ERROR_INTERNAL);
+ BnTo2B(bnM, inOut, inOut->size);
+ return TPM_RC_SUCCESS;
+}
+/* 10.2.17.4.5 OaepEncode() */
+/* This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must
+ equal the size of the modulus */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE hashAlg is not valid or message size is too large */
+static TPM_RC
+OaepEncode(
+ TPM2B *padded, // OUT: the pad data
+ TPM_ALG_ID hashAlg, // IN: algorithm to use for padding
+ const TPM2B *label, // IN: null-terminated string (may be NULL)
+ TPM2B *message, // IN: the message being padded
+ RAND_STATE *rand // IN: the random number generator to use
+ )
+{
+ INT32 padLen;
+ INT32 dbSize;
+ INT32 i;
+ BYTE mySeed[MAX_DIGEST_SIZE];
+ BYTE *seed = mySeed;
+ UINT16 hLen = CryptHashGetDigestSize(hashAlg);
+ BYTE mask[MAX_RSA_KEY_BYTES];
+ BYTE *pp;
+ BYTE *pm;
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ pAssert(padded != NULL && message != NULL);
+ // A value of zero is not allowed because the KDF can't produce a result
+ // if the digest size is zero.
+ if(hLen == 0)
+ return TPM_RC_VALUE;
+ // Basic size checks
+ // make sure digest isn't too big for key size
+ if(padded->size < (2 * hLen) + 2)
+ ERROR_RETURN(TPM_RC_HASH);
+ // and that message will fit messageSize <= k - 2hLen - 2
+ if(message->size > (padded->size - (2 * hLen) - 2))
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Hash L even if it is null
+ // Offset into padded leaving room for masked seed and byte of zero
+ pp = &padded->buffer[hLen + 1];
+ if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
+ hLen, pp) != hLen)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ // concatenate PS of k mLen 2hLen 2
+ padLen = padded->size - message->size - (2 * hLen) - 2;
+ MemorySet(&pp[hLen], 0, padLen);
+ pp[hLen + padLen] = 0x01;
+ padLen += 1;
+ memcpy(&pp[hLen + padLen], message->buffer, message->size);
+ // The total size of db = hLen + pad + mSize;
+ dbSize = hLen + padLen + message->size;
+ // If testing, then use the provided seed. Otherwise, use values
+ // from the RNG
+ CryptRandomGenerate(hLen, mySeed);
+ DRBG_Generate(rand, mySeed, (UINT16)hLen);
+ // mask = MGF1 (seed, nSize hLen 1)
+ CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0);
+ // Create the masked db
+ pm = mask;
+ for(i = dbSize; i > 0; i--)
+ *pp++ ^= *pm++;
+ pp = &padded->buffer[hLen + 1];
+ // Run the masked data through MGF1
+ if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) != (unsigned)hLen)
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Now XOR the seed to create masked seed
+ pp = &padded->buffer[1];
+ pm = seed;
+ for(i = hLen; i > 0; i--)
+ *pp++ ^= *pm++;
+ // Set the first byte to zero
+ padded->buffer[0] = 0x00;
+ Exit:
+ return retVal;
+}
+/* 10.2.17.4.6 OaepDecode() */
+/* This function performs OAEP padding checking. The size of the buffer to receive the recovered
+ data. If the padding is not valid, the dSize size is set to zero and the function returns
+ TPM_RC_VALUE. */
+/* The dSize parameter is used as an input to indicate the size available in the buffer. If
+ insufficient space is available, the size is not changed and the return code is TPM_RC_VALUE. */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE the value to decode was larger than the modulus, or the padding is wrong or the
+ buffer to receive the results is too small */
+static TPM_RC
+OaepDecode(
+ TPM2B *dataOut, // OUT: the recovered data
+ TPM_ALG_ID hashAlg, // IN: algorithm to use for padding
+ const TPM2B *label, // IN: null-terminated string (may be NULL)
+ TPM2B *padded // IN: the padded data
+ )
+{
+ UINT32 i;
+ BYTE seedMask[MAX_DIGEST_SIZE];
+ UINT32 hLen = CryptHashGetDigestSize(hashAlg);
+ BYTE mask[MAX_RSA_KEY_BYTES];
+ BYTE *pp;
+ BYTE *pm;
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ // Strange size (anything smaller can't be an OAEP padded block)
+ // Also check for no leading 0
+ if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0))
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Use the hash size to determine what to put through MGF1 in order
+ // to recover the seedMask
+ CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1,
+ &padded->buffer[hLen + 1], 0);
+ // Recover the seed into seedMask
+ pAssert(hLen <= sizeof(seedMask));
+ pp = &padded->buffer[1];
+ pm = seedMask;
+ for(i = hLen; i > 0; i--)
+ *pm++ ^= *pp++;
+ // Use the seed to generate the data mask
+ CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0);
+ // Use the mask generated from seed to recover the padded data
+ pp = &padded->buffer[hLen + 1];
+ pm = mask;
+ for(i = (padded->size - hLen - 1); i > 0; i--)
+ *pm++ ^= *pp++;
+ // Make sure that the recovered data has the hash of the label
+ // Put trial value in the seed mask
+ if((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
+ hLen, seedMask)) != hLen)
+ FAIL(FATAL_ERROR_INTERNAL);
+ if(memcmp(seedMask, mask, hLen) != 0)
+ ERROR_RETURN(TPM_RC_VALUE);
+ // find the start of the data
+ pm = &mask[hLen];
+ for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--)
+ {
+ if(*pm++ != 0)
+ break;
+ }
+ // If we ran out of data or didn't end with 0x01, then return an error
+ if(i == 0 || pm[-1] != 0x01)
+ ERROR_RETURN(TPM_RC_VALUE);
+ // pm should be pointing at the first part of the data
+ // and i is one greater than the number of bytes to move
+ i--;
+ if(i > dataOut->size)
+ // Special exit to preserve the size of the output buffer
+ return TPM_RC_VALUE;
+ memcpy(dataOut->buffer, pm, i);
+ dataOut->size = (UINT16)i;
+ Exit:
+ if(retVal != TPM_RC_SUCCESS)
+ dataOut->size = 0;
+ return retVal;
+}
+/* 10.2.17.4.7 PKCS1v1_5Encode() */
+/* This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE message size is too large */
+static TPM_RC
+RSAES_PKCS1v1_5Encode(
+ TPM2B *padded, // OUT: the pad data
+ TPM2B *message, // IN: the message being padded
+ RAND_STATE *rand
+ )
+{
+ UINT32 ps = padded->size - message->size - 3;
+ //
+ if(message->size > padded->size - 11)
+ return TPM_RC_VALUE;
+ // move the message to the end of the buffer
+ memcpy(&padded->buffer[padded->size - message->size], message->buffer,
+ message->size);
+ // Set the first byte to 0x00 and the second to 0x02
+ padded->buffer[0] = 0;
+ padded->buffer[1] = 2;
+ // Fill with random bytes
+ DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps);
+ // Set the delimiter for the random field to 0
+ padded->buffer[2 + ps] = 0;
+ // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero
+ // In this implementation, use the value of the current index
+ for(ps++; ps > 1; ps--)
+ {
+ if(padded->buffer[ps] == 0)
+ padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the
+ // random value is 0, just pick a value to
+ // put into the spot.
+ }
+ return TPM_RC_SUCCESS;
+}
+/* 10.2.17.4.8 RSAES_Decode() */
+/* This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */
+/* Error Returns Meaning */
+/* TPM_RC_FAIL decoding error or results would no fit into provided buffer */
+static TPM_RC
+RSAES_Decode(
+ TPM2B *message, // OUT: the recovered message
+ TPM2B *coded // IN: the encoded message
+ )
+{
+ BOOL fail = FALSE;
+ UINT16 pSize;
+ fail = (coded->size < 11);
+ fail = (coded->buffer[0] != 0x00) | fail;
+ fail = (coded->buffer[1] != 0x02) | fail;
+ for(pSize = 2; pSize < coded->size; pSize++)
+ {
+ if(coded->buffer[pSize] == 0)
+ break;
+ }
+ pSize++;
+ // Make sure that pSize has not gone over the end and that there are at least 8
+ // bytes of pad data.
+ fail = (pSize > coded->size) | fail;
+ fail = ((pSize - 2) <= 8) | fail;
+ if((message->size < (UINT16)(coded->size - pSize)) || fail)
+ return TPM_RC_VALUE;
+ message->size = coded->size - pSize;
+ memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize);
+ return TPM_RC_SUCCESS;
+}
+#endif // libtpms added
+/* 10.2.17.4.13 CryptRsaPssSaltSize() */
+/* This function computes the salt size used in PSS. It is broken out so that the X509 code can get
+ the same value that is used by the encoding function in this module. */
+INT16
+CryptRsaPssSaltSize(
+ INT16 hashSize,
+ INT16 outSize
+)
+{
+ INT16 saltSize;
+ //
+ // (Mask Length) = (outSize - hashSize - 1);
+ // Max saltSize is (Mask Length) - 1
+ saltSize = (outSize - hashSize - 1) - 1;
+ // Use the maximum salt size allowed by FIPS 186-4
+ if (saltSize > hashSize)
+ saltSize = hashSize;
+ else if (saltSize < 0)
+ saltSize = 0;
+ return saltSize;
+}
+
+#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
+/* 10.2.17.4.9 PssEncode() */
+/* This function creates an encoded block of data that is the size of modulus. The function uses the
+ maximum salt size that will fit in the encoded block. */
+/* Returns TPM_RC_SUCCESS or goes into failure mode. */
+static TPM_RC
+PssEncode(
+ TPM2B *out, // OUT: the encoded buffer
+ TPM_ALG_ID hashAlg, // IN: hash algorithm for the encoding
+ TPM2B *digest, // IN: the digest
+ RAND_STATE *rand // IN: random number source
+ )
+{
+ UINT32 hLen = CryptHashGetDigestSize(hashAlg);
+ BYTE salt[MAX_RSA_KEY_BYTES - 1];
+ UINT16 saltSize;
+ BYTE *ps = salt;
+ BYTE *pOut;
+ UINT16 mLen;
+ HASH_STATE hashState;
+ // These are fatal errors indicating bad TPM firmware
+ pAssert(out != NULL && hLen > 0 && digest != NULL);
+ // Get the size of the mask
+ mLen = (UINT16)(out->size - hLen - 1);
+ // Maximum possible salt size is mask length - 1
+ saltSize = mLen - 1;
+ // Use the maximum salt size allowed by FIPS 186-4
+ if(saltSize > hLen)
+ saltSize = (UINT16)hLen;
+ //using eOut for scratch space
+ // Set the first 8 bytes to zero
+ pOut = out->buffer;
+ memset(pOut, 0, 8);
+ // Get set the salt
+ DRBG_Generate(rand, salt, saltSize);
+ // Create the hash of the pad || input hash || salt
+ CryptHashStart(&hashState, hashAlg);
+ CryptDigestUpdate(&hashState, 8, pOut);
+ CryptDigestUpdate2B(&hashState, digest);
+ CryptDigestUpdate(&hashState, saltSize, salt);
+ CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]);
+ // Create a mask
+ if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen)
+ FAIL(FATAL_ERROR_INTERNAL);
+ // Since this implementation uses key sizes that are all even multiples of
+ // 8, just need to make sure that the most significant bit is CLEAR
+ *pOut &= 0x7f;
+ // Before we mess up the pOut value, set the last byte to 0xbc
+ pOut[out->size - 1] = 0xbc;
+ // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed
+ pOut = &pOut[mLen - saltSize - 1];
+ *pOut++ ^= 0x01;
+ // XOR the salt data into the buffer
+ for(; saltSize > 0; saltSize--)
+ *pOut++ ^= *ps++;
+ // and we are done
+ return TPM_RC_SUCCESS;
+}
+/* 10.2.17.4.10 PssDecode() */
+/* This function checks that the PSS encoded block was built from the provided digest. If the check
+ is successful, TPM_RC_SUCCESS is returned. Any other value indicates an error. */
+/* This implementation of PSS decoding is intended for the reference TPM implementation and is not
+ at all generalized. It is used to check signatures over hashes and assumptions are made about
+ the sizes of values. Those assumptions are enforce by this implementation. This implementation
+ does allow for a variable size salt value to have been used by the creator of the signature. */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */
+/* TPM_RC_VALUE decode operation failed */
+static TPM_RC
+PssDecode(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding
+ TPM2B *dIn, // In: the digest to compare
+ TPM2B *eIn // IN: the encoded data
+ )
+{
+ UINT32 hLen = CryptHashGetDigestSize(hashAlg);
+ BYTE mask[MAX_RSA_KEY_BYTES];
+ BYTE *pm = mask;
+ BYTE *pe;
+ BYTE pad[8] = {0};
+ UINT32 i;
+ UINT32 mLen;
+ BYTE fail;
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ HASH_STATE hashState;
+ // These errors are indicative of failures due to programmer error
+ pAssert(dIn != NULL && eIn != NULL);
+ pe = eIn->buffer;
+ // check the hash scheme
+ if(hLen == 0)
+ ERROR_RETURN(TPM_RC_SCHEME);
+ // most significant bit must be zero
+ fail = pe[0] & 0x80;
+ // last byte must be 0xbc
+ fail |= pe[eIn->size - 1] ^ 0xbc;
+ // Use the hLen bytes at the end of the buffer to generate a mask
+ // Doesn't start at the end which is a flag byte
+ mLen = eIn->size - hLen - 1;
+ CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0);
+ // Clear the MSO of the mask to make it consistent with the encoding.
+ mask[0] &= 0x7F;
+ pAssert(mLen <= sizeof(mask));
+ // XOR the data into the mask to recover the salt. This sequence
+ // advances eIn so that it will end up pointing to the seed data
+ // which is the hash of the signature data
+ for(i = mLen; i > 0; i--)
+ *pm++ ^= *pe++;
+ // Find the first byte of 0x01 after a string of all 0x00
+ for(pm = mask, i = mLen; i > 0; i--)
+ {
+ if(*pm == 0x01)
+ break;
+ else
+ fail |= *pm++;
+ }
+ // i should not be zero
+ fail |= (i == 0);
+ // if we have failed, will continue using the entire mask as the salt value so
+ // that the timing attacks will not disclose anything (I don't think that this
+ // is a problem for TPM applications but, usually, we don't fail so this
+ // doesn't cost anything).
+ if(fail)
+ {
+ i = mLen;
+ pm = mask;
+ }
+ else
+ {
+ pm++;
+ i--;
+ }
+ // i contains the salt size and pm points to the salt. Going to use the input
+ // hash and the seed to recreate the hash in the lower portion of eIn.
+ CryptHashStart(&hashState, hashAlg);
+ // add the pad of 8 zeros
+ CryptDigestUpdate(&hashState, 8, pad);
+ // add the provided digest value
+ CryptDigestUpdate(&hashState, dIn->size, dIn->buffer);
+ // and the salt
+ CryptDigestUpdate(&hashState, i, pm);
+ // get the result
+ fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen);
+ // Compare all bytes
+ for(pm = mask; hLen > 0; hLen--)
+ // don't use fail = because that could skip the increment and compare
+ // operations after the first failure and that gives away timing
+ // information.
+ fail |= *pm++ ^ *pe++;
+ retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
+ Exit:
+ return retVal;
+}
+/* 10.2.17.4.16 MakeDerTag() */
+/* Construct the DER value that is used in RSASSA */
+/* Return Value Meaning */
+/* > 0 size of value */
+/* <= 0 no hash exists */
+INT16
+MakeDerTag(
+ TPM_ALG_ID hashAlg,
+ INT16 sizeOfBuffer,
+ BYTE *buffer
+ )
+{
+ // 0x30, 0x31, // SEQUENCE (2 elements) 1st
+ // 0x30, 0x0D, // SEQUENCE (2 elements)
+ // 0x06, 0x09, // HASH OID
+ // 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ // 0x05, 0x00, // NULL
+ // 0x04, 0x20 // OCTET STRING
+ HASH_DEF *info = CryptGetHashDef(hashAlg);
+ INT16 oidSize;
+ // If no OID, can't do encode
+ VERIFY(info != NULL);
+ oidSize = 2 + (info->OID)[1];
+ // make sure this fits in the buffer
+ VERIFY(sizeOfBuffer >= (oidSize + 8));
+ *buffer++ = 0x30; // 1st SEQUENCE
+ // Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the
+ // digest size
+ *buffer++ = (BYTE)(6 + oidSize + info->digestSize); //
+ *buffer++ = 0x30; // 2nd SEQUENCE
+ // size is 4 bytes of overhead plus the side of the OID
+ *buffer++ = (BYTE)(2 + oidSize);
+ MemoryCopy(buffer, info->OID, oidSize);
+ buffer += oidSize;
+ *buffer++ = 0x05; // Add a NULL
+ *buffer++ = 0x00;
+
+ *buffer++ = 0x04;
+ *buffer++ = (BYTE)(info->digestSize);
+ return oidSize + 8;
+ Error:
+ return 0;
+
+}
+
+/* 10.2.17.4.17 RSASSA_Encode() */
+/* Encode a message using PKCS1v1.5 method. */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */
+/* TPM_RC_SIZE eOutSize is not large enough */
+/* TPM_RC_VALUE hInSize does not match the digest size of hashAlg */
+static TPM_RC
+RSASSA_Encode(
+ TPM2B *pOut, // IN:OUT on in, the size of the public key
+ // on out, the encoded area
+ TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5
+ TPM2B *hIn // IN: digest value to encode
+ )
+{
+ BYTE DER[20];
+ BYTE *der = DER;
+ INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER);
+ BYTE *eOut;
+ INT32 fillSize;
+ TPM_RC retVal = TPM_RC_SUCCESS;
+
+ // Can't use this scheme if the algorithm doesn't have a DER string defined.
+ if(derSize == 0)
+ ERROR_RETURN(TPM_RC_SCHEME);
+
+ // If the digest size of 'hashAl' doesn't match the input digest size, then
+ // the DER will misidentify the digest so return an error
+ if(CryptHashGetDigestSize(hashAlg) != hIn->size)
+ ERROR_RETURN(TPM_RC_VALUE);
+ fillSize = pOut->size - derSize - hIn->size - 3;
+ eOut = pOut->buffer;
+
+ // Make sure that this combination will fit in the provided space
+ if(fillSize < 8)
+ ERROR_RETURN(TPM_RC_SIZE);
+
+ // Start filling
+ *eOut++ = 0; // initial byte of zero
+ *eOut++ = 1; // byte of 0x01
+ for(; fillSize > 0; fillSize--)
+ *eOut++ = 0xff; // bunch of 0xff
+ *eOut++ = 0; // another 0
+ for(; derSize > 0; derSize--)
+ *eOut++ = *der++; // copy the DER
+ der = hIn->buffer;
+ for(fillSize = hIn->size; fillSize > 0; fillSize--)
+ *eOut++ = *der++; // copy the hash
+ Exit:
+ return retVal;
+}
+
+/* 10.2.17.4.18 RSASSA_Decode() */
+/* This function performs the RSASSA decoding of a signature. */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE decode unsuccessful */
+/* TPM_RC_SCHEME haslAlg is not supported */
+static TPM_RC
+RSASSA_Decode(
+ TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding
+ TPM2B *hIn, // In: the digest to compare
+ TPM2B *eIn // IN: the encoded data
+ )
+{
+ BYTE fail;
+ BYTE DER[20];
+ BYTE *der = DER;
+ INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER);
+ BYTE *pe;
+ INT32 hashSize = CryptHashGetDigestSize(hashAlg);
+ INT32 fillSize;
+ TPM_RC retVal;
+ BYTE *digest;
+ UINT16 digestSize;
+
+ pAssert(hIn != NULL && eIn != NULL);
+ pe = eIn->buffer;
+
+ // Can't use this scheme if the algorithm doesn't have a DER string
+ // defined or if the provided hash isn't the right size
+ if(derSize == 0 || (unsigned)hashSize != hIn->size)
+ ERROR_RETURN(TPM_RC_SCHEME);
+
+ // Make sure that this combination will fit in the provided space
+ // Since no data movement takes place, can just walk though this
+ // and accept nearly random values. This can only be called from
+ // CryptValidateSignature() so eInSize is known to be in range.
+ fillSize = eIn->size - derSize - hashSize - 3;
+
+ // Start checking (fail will become non-zero if any of the bytes do not have
+ // the expected value.
+ fail = *pe++; // initial byte of zero
+ fail |= *pe++ ^ 1; // byte of 0x01
+ for(; fillSize > 0; fillSize--)
+ fail |= *pe++ ^ 0xff; // bunch of 0xff
+ fail |= *pe++; // another 0
+ for(; derSize > 0; derSize--)
+ fail |= *pe++ ^ *der++; // match the DER
+ digestSize = hIn->size;
+ digest = hIn->buffer;
+ for(; digestSize > 0; digestSize--)
+ fail |= *pe++ ^ *digest++; // match the hash
+ retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
+ Exit:
+ return retVal;
+}
+#endif // libtpms added
+
+/* 10.2.17.4.13 CryptRsaSelectScheme() */
+/* This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to
+ select a scheme between input and object default. This function assume the RSA object is
+ loaded. If a default scheme is defined in object, the default scheme should be chosen, otherwise,
+ the input scheme should be chosen. In the case that both the object and scheme are not
+ TPM_ALG_NULL, then if the schemes are the same, the input scheme will be chosen. if the scheme
+ are not compatible, a NULL pointer will be returned. */
+/* The return pointer may point to a TPM_ALG_NULL scheme. */
+TPMT_RSA_DECRYPT*
+CryptRsaSelectScheme(
+ TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key
+ TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme
+ )
+{
+ OBJECT *rsaObject;
+ TPMT_ASYM_SCHEME *keyScheme;
+ TPMT_RSA_DECRYPT *retVal = NULL;
+ // Get sign object pointer
+ rsaObject = HandleToObject(rsaHandle);
+ keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme;
+ // if the default scheme of the object is TPM_ALG_NULL, then select the
+ // input scheme
+ if(keyScheme->scheme == TPM_ALG_NULL)
+ {
+ retVal = scheme;
+ }
+ // if the object scheme is not TPM_ALG_NULL and the input scheme is
+ // TPM_ALG_NULL, then select the default scheme of the object.
+ else if(scheme->scheme == TPM_ALG_NULL)
+ {
+ // if input scheme is NULL
+ retVal = (TPMT_RSA_DECRYPT *)keyScheme;
+ }
+ // get here if both the object scheme and the input scheme are
+ // not TPM_ALG_NULL. Need to insure that they are the same.
+ // IMPLEMENTATION NOTE: This could cause problems if future versions have
+ // schemes that have more values than just a hash algorithm. A new function
+ // (IsSchemeSame()) might be needed then.
+ else if(keyScheme->scheme == scheme->scheme
+ && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)
+ {
+ retVal = scheme;
+ }
+ // two different, incompatible schemes specified will return NULL
+ return retVal;
+}
+/* 10.2.17.4.14 CryptRsaLoadPrivateExponent() */
+/* Error Returns Meaning */
+/* TPM_RC_BINDING public and private parts of rsaKey are not matched */
+TPM_RC
+CryptRsaLoadPrivateExponent(
+ OBJECT *rsaKey // IN: the RSA key object
+ )
+{
+ BN_RSA_INITIALIZED(bnN, &rsaKey->publicArea.unique.rsa);
+ BN_PRIME_INITIALIZED(bnP, &rsaKey->sensitive.sensitive.rsa);
+ BN_RSA(bnQ);
+ BN_PRIME(bnQr);
+ BN_WORD_INITIALIZED(bnE, (rsaKey->publicArea.parameters.rsaDetail.exponent == 0)
+ ? RSA_DEFAULT_PUBLIC_EXPONENT
+ : rsaKey->publicArea.parameters.rsaDetail.exponent);
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ if(!rsaKey->attributes.privateExp)
+ {
+ TEST(TPM_ALG_NULL);
+ // Make sure that the bigNum used for the exponent is properly initialized
+ RsaInitializeExponent(&rsaKey->privateExponent);
+ // Find the second prime by division
+ BnDiv(bnQ, bnQr, bnN, bnP);
+ if(!BnEqualZero(bnQr))
+ ERROR_RETURN(TPM_RC_BINDING);
+ // Compute the private exponent and return it if found
+ if(!ComputePrivateExponent(bnP, bnQ, bnE, bnN,
+ &rsaKey->privateExponent))
+ ERROR_RETURN(TPM_RC_BINDING);
+ }
+ Exit:
+ rsaKey->attributes.privateExp = (retVal == TPM_RC_SUCCESS);
+ return retVal;
+}
+#if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
+/* 10.2.17.4.15 CryptRsaEncrypt() */
+/* This is the entry point for encryption using RSA. Encryption is use of the public exponent. The
+ padding parameter determines what padding will be used. */
+/* The cOutSize parameter must be at least as large as the size of the key. */
+/* If the padding is RSA_PAD_NONE, dIn is treated as a number. It must be lower in value than the
+ key modulus. */
+/* NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the
+ size of the RSA key for the call to RSAEP. This is because the high order bytes of dIn might have
+ a numeric value that is greater than the value of the key modulus. If this had low-order zeros
+ added, it would have a numeric value larger than the modulus even though it started out with a
+ lower numeric value. */
+/* Error Returns Meaning */
+/* TPM_RC_VALUE cOutSize is too small (must be the size of the modulus) */
+/* TPM_RC_SCHEME padType is not a supported scheme */
+LIB_EXPORT TPM_RC
+CryptRsaEncrypt(
+ TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data
+ TPM2B *dIn, // IN: the data to encrypt
+ OBJECT *key, // IN: the key used for encryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash
+ // if needed
+ const TPM2B *label, // IN: in case it is needed
+ RAND_STATE *rand // IN: random number generator
+ // state (mostly for testing)
+ )
+{
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ TPM2B_PUBLIC_KEY_RSA dataIn;
+ //
+ // if the input and output buffers are the same, copy the input to a scratch
+ // buffer so that things don't get messed up.
+ if(dIn == &cOut->b)
+ {
+ MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer));
+ dIn = &dataIn.b;
+ }
+ // All encryption schemes return the same size of data
+ cOut->t.size = key->publicArea.unique.rsa.t.size;
+ TEST(scheme->scheme);
+ switch(scheme->scheme)
+ {
+ case TPM_ALG_NULL: // 'raw' encryption
+ {
+ INT32 i;
+ INT32 dSize = dIn->size;
+ // dIn can have more bytes than cOut as long as the extra bytes
+ // are zero. Note: the more significant bytes of a number in a byte
+ // buffer are the bytes at the start of the array.
+ for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++);
+ dSize -= i;
+ if(dSize > cOut->t.size)
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Pad cOut with zeros if dIn is smaller
+ memset(cOut->t.buffer, 0, cOut->t.size - dSize);
+ // And copy the rest of the value
+ memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize);
+ // If the size of dIn is the same as cOut dIn could be larger than
+ // the modulus. If it is, then RSAEP() will catch it.
+ }
+ break;
+ case TPM_ALG_RSAES:
+ retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand);
+ break;
+ case TPM_ALG_OAEP:
+ retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn,
+ rand);
+ break;
+ default:
+ ERROR_RETURN(TPM_RC_SCHEME);
+ break;
+ }
+ // All the schemes that do padding will come here for the encryption step
+ // Check that the Encoding worked
+ if(retVal == TPM_RC_SUCCESS)
+ // Padding OK so do the encryption
+ retVal = RSAEP(&cOut->b, key);
+ Exit:
+ return retVal;
+}
+/* 10.2.17.4.16 CryptRsaDecrypt() */
+/* This is the entry point for decryption using RSA. Decryption is use of the private exponent. The
+ padType parameter determines what padding was used. */
+/* Error Returns Meaning */
+/* TPM_RC_SIZE cInSize is not the same as the size of the public modulus of key; or numeric value of
+ the encrypted data is greater than the modulus */
+/* TPM_RC_VALUE dOutSize is not large enough for the result */
+/* TPM_RC_SCHEME padType is not supported */
+LIB_EXPORT TPM_RC
+CryptRsaDecrypt(
+ TPM2B *dOut, // OUT: the decrypted data
+ TPM2B *cIn, // IN: the data to decrypt
+ OBJECT *key, // IN: the key to use for decryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme
+ const TPM2B *label // IN: in case it is needed for the scheme
+ )
+{
+ TPM_RC retVal;
+ // Make sure that the necessary parameters are provided
+ pAssert(cIn != NULL && dOut != NULL && key != NULL);
+ // Size is checked to make sure that the encrypted value is the right size
+ if(cIn->size != key->publicArea.unique.rsa.t.size)
+ ERROR_RETURN(TPM_RC_SIZE);
+ TEST(scheme->scheme);
+ // For others that do padding, do the decryption in place and then
+ // go handle the decoding.
+ retVal = RSADP(cIn, key);
+ if(retVal == TPM_RC_SUCCESS)
+ {
+ // Remove padding
+ switch(scheme->scheme)
+ {
+ case TPM_ALG_NULL:
+ if(dOut->size < cIn->size)
+ return TPM_RC_VALUE;
+ MemoryCopy2B(dOut, cIn, dOut->size);
+ break;
+ case TPM_ALG_RSAES:
+ retVal = RSAES_Decode(dOut, cIn);
+ break;
+ case TPM_ALG_OAEP:
+ retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn);
+ break;
+ default:
+ retVal = TPM_RC_SCHEME;
+ break;
+ }
+ }
+ Exit:
+ return retVal;
+}
+/* 10.2.17.4.17 CryptRsaSign() */
+/* This function is used to generate an RSA signature of the type indicated in scheme. */
+/* Error Returns Meaning */
+/* TPM_RC_SCHEME scheme or hashAlg are not supported */
+/* TPM_RC_VALUE hInSize does not match hashAlg (for RSASSA) */
+LIB_EXPORT TPM_RC
+CryptRsaSign(
+ TPMT_SIGNATURE *sigOut,
+ OBJECT *key, // IN: key to use
+ TPM2B_DIGEST *hIn, // IN: the digest to sign
+ RAND_STATE *rand // IN: the random number generator
+ // to use (mostly for testing)
+ )
+{
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ UINT16 modSize;
+ // parameter checks
+ pAssert(sigOut != NULL && key != NULL && hIn != NULL);
+ modSize = key->publicArea.unique.rsa.t.size;
+ // for all non-null signatures, the size is the size of the key modulus
+ sigOut->signature.rsapss.sig.t.size = modSize;
+ TEST(sigOut->sigAlg);
+ switch(sigOut->sigAlg)
+ {
+ case TPM_ALG_NULL:
+ sigOut->signature.rsapss.sig.t.size = 0;
+ return TPM_RC_SUCCESS;
+ case TPM_ALG_RSAPSS:
+ retVal = PssEncode(&sigOut->signature.rsapss.sig.b,
+ sigOut->signature.rsapss.hash, &hIn->b, rand);
+ break;
+ case TPM_ALG_RSASSA:
+ retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b,
+ sigOut->signature.rsassa.hash, &hIn->b);
+ break;
+ default:
+ retVal = TPM_RC_SCHEME;
+ }
+ if(retVal == TPM_RC_SUCCESS)
+ {
+ // Do the encryption using the private key
+ retVal = RSADP(&sigOut->signature.rsapss.sig.b, key);
+ }
+ return retVal;
+}
+/* 10.2.17.4.18 CryptRsaValidateSignature() */
+/* This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS is
+ returned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes
+ indicate either parameter problems or fatal errors. */
+/* Error Returns Meaning */
+/* TPM_RC_SIGNATURE the signature does not check */
+/* TPM_RC_SCHEME unsupported scheme or hash algorithm */
+LIB_EXPORT TPM_RC
+CryptRsaValidateSignature(
+ TPMT_SIGNATURE *sig, // IN: signature
+ OBJECT *key, // IN: public modulus
+ TPM2B_DIGEST *digest // IN: The digest being validated
+ )
+{
+ TPM_RC retVal;
+ //
+ // Fatal programming errors
+ pAssert(key != NULL && sig != NULL && digest != NULL);
+ switch(sig->sigAlg)
+ {
+ case TPM_ALG_RSAPSS:
+ case TPM_ALG_RSASSA:
+ break;
+ default:
+ return TPM_RC_SCHEME;
+ }
+ // Errors that might be caused by calling parameters
+ if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size)
+ ERROR_RETURN(TPM_RC_SIGNATURE);
+ TEST(sig->sigAlg);
+ // Decrypt the block
+ retVal = RSAEP(&sig->signature.rsassa.sig.b, key);
+ if(retVal == TPM_RC_SUCCESS)
+ {
+ switch(sig->sigAlg)
+ {
+ case TPM_ALG_RSAPSS:
+ retVal = PssDecode(sig->signature.any.hashAlg, &digest->b,
+ &sig->signature.rsassa.sig.b);
+ break;
+ case TPM_ALG_RSASSA:
+ retVal = RSASSA_Decode(sig->signature.any.hashAlg, &digest->b,
+ &sig->signature.rsassa.sig.b);
+ break;
+ default:
+ return TPM_RC_SCHEME;
+ }
+ }
+ Exit:
+ return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS;
+}
+#endif // libtpms added
+#if SIMULATION && USE_RSA_KEY_CACHE
+extern int s_rsaKeyCacheEnabled;
+int GetCachedRsaKey(OBJECT *key, RAND_STATE *rand);
+#define GET_CACHED_KEY(key, rand) \
+ (s_rsaKeyCacheEnabled && GetCachedRsaKey(key, rand))
+#else
+#define GET_CACHED_KEY(key, rand)
+#endif
+/* 10.2.17.4.19 CryptRsaGenerateKey() */
+/* Generate an RSA key from a provided seed */
+/* Error Returns Meaning */
+/* TPM_RC_CANCELED operation was canceled */
+/* TPM_RC_RANGE public exponent is not supported */
+/* TPM_RC_VALUE could not find a prime using the provided parameters */
+LIB_EXPORT TPM_RC
+CryptRsaGenerateKey(
+ OBJECT *rsaKey, // IN/OUT: The object structure in which
+ // the key is created.
+ RAND_STATE *rand // IN: if not NULL, the deterministic
+ // RNG state
+ )
+{
+ UINT32 i;
+ BN_PRIME(bnP); // These four declarations initialize the number to 0
+ BN_PRIME(bnQ);
+ BN_RSA(bnD);
+ BN_RSA(bnN);
+ BN_WORD(bnE);
+ UINT32 e;
+ int keySizeInBits;
+ TPMT_PUBLIC *publicArea = &rsaKey->publicArea;
+ TPMT_SENSITIVE *sensitive = &rsaKey->sensitive;
+ TPM_RC retVal = TPM_RC_NO_RESULT;
+ //
+ // Need to make sure that the caller did not specify an exponent that is
+ // not supported
+ e = publicArea->parameters.rsaDetail.exponent;
+ if(e == 0)
+ e = RSA_DEFAULT_PUBLIC_EXPONENT;
+ if(e < 65537)
+ ERROR_RETURN(TPM_RC_RANGE);
+ if(e != RSA_DEFAULT_PUBLIC_EXPONENT && !IsPrimeInt(e))
+ ERROR_RETURN(TPM_RC_RANGE);
+ BnSetWord(bnE, e);
+ // Check that e is prime
+ // check for supported key size.
+ keySizeInBits = publicArea->parameters.rsaDetail.keyBits;
+ if(((keySizeInBits % 1024) != 0)
+ || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but...
+ || (keySizeInBits == 0))
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Set the prime size for instrumentation purposes
+ INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2));
+#if SIMULATION && USE_RSA_KEY_CACHE
+ if(GET_CACHED_KEY(rsaKey, rand))
+ return TPM_RC_SUCCESS;
+#endif
+ // Make sure that key generation has been tested
+ TEST(TPM_ALG_NULL);
+#if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin
+ if (rand == NULL)
+ return OpenSSLCryptRsaGenerateKey(rsaKey, e, keySizeInBits);
+#endif // libtpms added end
+ // Need to initialize the privateExponent structure
+ RsaInitializeExponent(&rsaKey->privateExponent);
+ // The prime is computed in P. When a new prime is found, Q is checked to
+ // see if it is zero. If so, P is copied to Q and a new P is found.
+ // When both P and Q are non-zero, the modulus and
+ // private exponent are computed and a trial encryption/decryption is
+ // performed. If the encrypt/decrypt fails, assume that at least one of the
+ // primes is composite. Since we don't know which one, set Q to zero and start
+ // over and find a new pair of primes.
+ for(i = 1; (retVal != TPM_RC_SUCCESS) && (i != 100); i++)
+ {
+ if(_plat__IsCanceled())
+ ERROR_RETURN(TPM_RC_CANCELED);
+ BnGeneratePrimeForRSA(bnP, keySizeInBits / 2, e, rand);
+ INSTRUMENT_INC(PrimeCounts[PrimeIndex]);
+ // If this is the second prime, make sure that it differs from the
+ // first prime by at least 2^100
+ if(BnEqualZero(bnQ))
+ {
+ // copy p to q and compute another prime in p
+ BnCopy(bnQ, bnP);
+ continue;
+ }
+ // Make sure that the difference is at least 100 bits. Need to do it this
+ // way because the big numbers are only positive values
+ if(BnUnsignedCmp(bnP, bnQ) < 0)
+ BnSub(bnD, bnQ, bnP);
+ else
+ BnSub(bnD, bnP, bnQ);
+ if(BnMsb(bnD) < 100)
+ continue;
+ //Form the public modulus and set the unique value
+ BnMult(bnN, bnP, bnQ);
+ BnTo2B(bnN, &publicArea->unique.rsa.b,
+ (NUMBYTES)BITS_TO_BYTES(keySizeInBits));
+ // And the prime to the sensitive area
+ BnTo2B(bnP, &sensitive->sensitive.rsa.b,
+ (NUMBYTES)BITS_TO_BYTES(keySizeInBits) / 2);
+ // Make sure everything came out right. The MSb of the values must be
+ // one
+ if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0)
+ || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0))
+ FAIL(FATAL_ERROR_INTERNAL);
+ // Make sure that we can form the private exponent values
+ if(ComputePrivateExponent(bnP, bnQ, bnE, bnN, &rsaKey->privateExponent)
+ != TRUE)
+ {
+ // If ComputePrivateExponent could not find an inverse for
+ // Q, then copy P and recompute P. This might
+ // cause both to be recomputed if P is also zero
+ if(BnEqualZero(bnQ))
+ BnCopy(bnQ, bnP);
+ continue;
+ }
+ retVal = TPM_RC_SUCCESS;
+ // Do a trial encryption decryption if this is a signing key
+ if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
+ {
+ BN_RSA(temp1);
+ BN_RSA(temp2);
+ BnGenerateRandomInRange(temp1, bnN, rand);
+ // Encrypt with public exponent...
+ BnModExp(temp2, temp1, bnE, bnN);
+ // ... then decrypt with private exponent
+ RsaPrivateKeyOp(temp2, bnN, bnP, &rsaKey->privateExponent);
+ // If the starting and ending values are not the same,
+ // start over )-;
+ if(BnUnsignedCmp(temp2, temp1) != 0)
+ {
+ BnSetWord(bnQ, 0);
+ retVal = TPM_RC_NO_RESULT;
+ }
+ }
+ }
+ Exit:
+ if(retVal == TPM_RC_SUCCESS)
+ rsaKey->attributes.privateExp = SET;
+ return retVal;
+}
+
+#if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin
+LIB_EXPORT TPM_RC
+CryptRsaEncrypt(
+ TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data
+ TPM2B *dIn, // IN: the data to encrypt
+ OBJECT *key, // IN: the key used for encryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash
+ // if needed
+ const TPM2B *label, // IN: in case it is needed
+ RAND_STATE *rand // IN: random number generator
+ // state (mostly for testing)
+ )
+{
+ TPM_RC retVal;
+ TPM2B_PUBLIC_KEY_RSA dataIn;
+ TPM2B_PUBLIC_KEY_RSA scratch;
+ size_t outlen;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_MD *md;
+ const char *digestname;
+ unsigned char *tmp = NULL;
+ //
+ // if the input and output buffers are the same, copy the input to a scratch
+ // buffer so that things don't get messed up.
+ if(dIn == &cOut->b)
+ {
+ MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer));
+ dIn = &dataIn.b;
+ }
+ // All encryption schemes return the same size of data
+ pAssert(sizeof(cOut->t.buffer) >= key->publicArea.unique.rsa.t.size);
+ cOut->t.size = key->publicArea.unique.rsa.t.size;
+ TEST(scheme->scheme);
+
+ retVal = InitOpenSSLRSAPublicKey(key, &pkey);
+ if (retVal != TPM_RC_SUCCESS)
+ return retVal;
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (ctx == NULL ||
+ EVP_PKEY_encrypt_init(ctx) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ switch(scheme->scheme)
+ {
+ case TPM_ALG_NULL: // 'raw' encryption
+ {
+ INT32 i;
+ INT32 dSize = dIn->size;
+ // dIn can have more bytes than cOut as long as the extra bytes
+ // are zero. Note: the more significant bytes of a number in a byte
+ // buffer are the bytes at the start of the array.
+ for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++);
+ dSize -= i;
+ scratch.t.size = cOut->t.size;
+ pAssert(scratch.t.size <= sizeof(scratch.t.buffer));
+ if(dSize > scratch.t.size)
+ ERROR_RETURN(TPM_RC_VALUE);
+ // Pad cOut with zeros if dIn is smaller
+ memset(scratch.t.buffer, 0, scratch.t.size - dSize);
+ // And copy the rest of the value; value is then right-aligned
+ memcpy(&scratch.t.buffer[scratch.t.size - dSize], &dIn->buffer[i], dSize);
+
+ dIn = &scratch.b;
+ }
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ break;
+ case TPM_ALG_RSAES:
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ break;
+ case TPM_ALG_OAEP:
+ digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg);
+ if (digestname == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+
+ md = EVP_get_digestbyname(digestname);
+ 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)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (label->size > 0) {
+ tmp = malloc(label->size);
+ if (tmp == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ memcpy(tmp, label->buffer, label->size);
+ }
+ // label->size == 0 is supported
+ if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ tmp = NULL;
+ break;
+ default:
+ ERROR_RETURN(TPM_RC_SCHEME);
+ break;
+ }
+
+ outlen = cOut->t.size;
+
+ if (EVP_PKEY_encrypt(ctx, cOut->t.buffer, &outlen,
+ dIn->buffer, dIn->size) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ cOut->t.size = outlen;
+
+ Exit:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ free(tmp);
+
+ return retVal;
+}
+
+LIB_EXPORT TPM_RC
+CryptRsaDecrypt(
+ TPM2B *dOut, // OUT: the decrypted data
+ TPM2B *cIn, // IN: the data to decrypt
+ OBJECT *key, // IN: the key to use for decryption
+ TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme
+ const TPM2B *label // IN: in case it is needed for the scheme
+ )
+{
+ TPM_RC retVal;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_MD *md = NULL;
+ const char *digestname;
+ size_t outlen;
+ unsigned char *tmp = NULL;
+ unsigned char buffer[MAX_RSA_KEY_BYTES];
+
+ // Make sure that the necessary parameters are provided
+ pAssert(cIn != NULL && dOut != NULL && key != NULL);
+ // Size is checked to make sure that the encrypted value is the right size
+ if(cIn->size != key->publicArea.unique.rsa.t.size)
+ ERROR_RETURN(TPM_RC_SIZE);
+ TEST(scheme->scheme);
+
+ retVal = InitOpenSSLRSAPrivateKey(key, &pkey);
+ if (retVal != TPM_RC_SUCCESS)
+ return retVal;
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (ctx == NULL ||
+ EVP_PKEY_decrypt_init(ctx) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ switch(scheme->scheme)
+ {
+ case TPM_ALG_NULL: // 'raw' encryption
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ break;
+ case TPM_ALG_RSAES:
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ break;
+ case TPM_ALG_OAEP:
+ digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg);
+ if (digestname == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+
+ md = EVP_get_digestbyname(digestname);
+ 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)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (label->size > 0) {
+ tmp = malloc(label->size);
+ if (tmp == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ memcpy(tmp, label->buffer, label->size);
+
+ if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ tmp = NULL;
+ }
+ break;
+ default:
+ ERROR_RETURN(TPM_RC_SCHEME);
+ break;
+ }
+
+ /* cannot use cOut->buffer */
+ outlen = sizeof(buffer);
+ if (EVP_PKEY_decrypt(ctx, buffer, &outlen,
+ cIn->buffer, cIn->size) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (outlen > dOut->size)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ memcpy(dOut->buffer, buffer, outlen);
+ dOut->size = outlen;
+
+ retVal = TPM_RC_SUCCESS;
+
+ Exit:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ free(tmp);
+
+ return retVal;
+}
+
+LIB_EXPORT TPM_RC
+CryptRsaSign(
+ TPMT_SIGNATURE *sigOut,
+ OBJECT *key, // IN: key to use
+ TPM2B_DIGEST *hIn, // IN: the digest to sign
+ RAND_STATE *rand // IN: the random number generator
+ // to use (mostly for testing)
+ )
+{
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ UINT16 modSize;
+ size_t outlen;
+ int padding;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_MD *md;
+ const char *digestname;
+ TPMI_ALG_HASH hashAlg;
+
+ // parameter checks
+ pAssert(sigOut != NULL && key != NULL && hIn != NULL);
+ modSize = key->publicArea.unique.rsa.t.size;
+ // for all non-null signatures, the size is the size of the key modulus
+ sigOut->signature.rsapss.sig.t.size = modSize;
+ TEST(sigOut->sigAlg);
+
+ switch(sigOut->sigAlg)
+ {
+ case TPM_ALG_NULL:
+ sigOut->signature.rsapss.sig.t.size = 0;
+ return TPM_RC_SUCCESS;
+ case TPM_ALG_RSAPSS:
+ padding = RSA_PKCS1_PSS_PADDING;
+ hashAlg = sigOut->signature.rsapss.hash;
+ break;
+ case TPM_ALG_RSASSA:
+ padding = RSA_PKCS1_PADDING;
+ hashAlg = sigOut->signature.rsassa.hash;
+ break;
+ default:
+ ERROR_RETURN(TPM_RC_SCHEME);
+ }
+
+ digestname = GetDigestNameByHashAlg(hashAlg);
+ if (digestname == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+
+ md = EVP_get_digestbyname(digestname);
+ if (md == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ retVal = InitOpenSSLRSAPrivateKey(key, &pkey);
+ if (retVal != TPM_RC_SUCCESS)
+ return retVal;
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (ctx == NULL ||
+ EVP_PKEY_sign_init(ctx) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ /* careful with PSS padding: Use salt length = hash length (-1) if
+ * length(digest) + length(hash-to-sign) + 2 <= modSize
+ * otherwise use the max. possible salt length, which is the default (-2)
+ * test case: 1024 bit key PSS signing sha512 hash
+ */
+ if (padding == RSA_PKCS1_PSS_PADDING &&
+ EVP_MD_size(md) + hIn->b.size + 2 <= modSize && /* OSSL: RSA_padding_add_PKCS1_PSS_mgf1 */
+ EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ outlen = sigOut->signature.rsapss.sig.t.size;
+ if (EVP_PKEY_sign(ctx,
+ sigOut->signature.rsapss.sig.t.buffer, &outlen,
+ hIn->b.buffer, hIn->b.size) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ sigOut->signature.rsapss.sig.t.size = outlen;
+
+ Exit:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+
+ return retVal;
+}
+
+LIB_EXPORT TPM_RC
+CryptRsaValidateSignature(
+ TPMT_SIGNATURE *sig, // IN: signature
+ OBJECT *key, // IN: public modulus
+ TPM2B_DIGEST *digest // IN: The digest being validated
+ )
+{
+ TPM_RC retVal;
+ int padding;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_MD *md;
+ const char *digestname;
+
+ //
+ // Fatal programming errors
+ pAssert(key != NULL && sig != NULL && digest != NULL);
+ switch(sig->sigAlg)
+ {
+ case TPM_ALG_RSAPSS:
+ padding = RSA_PKCS1_PSS_PADDING;
+ break;
+ case TPM_ALG_RSASSA:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ default:
+ return TPM_RC_SCHEME;
+ }
+ // Errors that might be caused by calling parameters
+ if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size)
+ ERROR_RETURN(TPM_RC_SIGNATURE);
+ TEST(sig->sigAlg);
+
+ retVal = InitOpenSSLRSAPublicKey(key, &pkey);
+ if (retVal != TPM_RC_SUCCESS)
+ return retVal;
+
+ digestname = GetDigestNameByHashAlg(sig->signature.any.hashAlg);
+ if (digestname == NULL)
+ ERROR_RETURN(TPM_RC_VALUE);
+
+ md = EVP_get_digestbyname(digestname);
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (md == NULL || ctx == NULL ||
+ EVP_PKEY_verify_init(ctx) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (EVP_PKEY_verify(ctx,
+ sig->signature.rsassa.sig.t.buffer, sig->signature.rsassa.sig.t.size,
+ digest->t.buffer, digest->t.size) <= 0)
+ ERROR_RETURN(TPM_RC_SIGNATURE);
+
+ retVal = TPM_RC_SUCCESS;
+
+ Exit:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+
+ return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS;
+}
+#endif // USE_OPENSSL_FUNCTIONS_RSA libtpms added end
+
+#endif // TPM_ALG_RSA
diff --git a/src/tpm2/crypto/openssl/CryptSmac.c b/src/tpm2/crypto/openssl/CryptSmac.c
new file mode 100644
index 0000000..c4b3515
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptSmac.c
@@ -0,0 +1,156 @@
+/********************************************************************************/
+/* */
+/* Message Authentication Codes Based on a Symmetric Block Cipher */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2018 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.20 CryptSmac.c */
+/* 10.2.20.1 Introduction */
+/* This file contains the implementation of the message authentication codes based on a symmetric
+ block cipher. These functions only use the single block encryption functions of the selected
+ symmetric cryptographic library. */
+/* 10.2.20.2 Includes, Defines, and Typedefs */
+#define _CRYPT_HASH_C_
+#include "Tpm.h"
+#if SMAC_IMPLEMENTED
+ /* 10.2.20.2.1 CryptSmacStart() */
+ /* Function to start an SMAC. */
+UINT16
+CryptSmacStart(
+ HASH_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParameters,
+ TPM_ALG_ID macAlg, // IN: the type of MAC
+ TPM2B *key
+ )
+{
+ UINT16 retVal = 0;
+ //
+ // Make sure that the key size is correct. This should have been checked
+ // at key load, but...
+ if(BITS_TO_BYTES(keyParameters->symDetail.sym.keyBits.sym) == key->size)
+ {
+ switch(macAlg)
+ {
+#if ALG_CMAC
+ case TPM_ALG_CMAC:
+ retVal = CryptCmacStart(&state->state.smac, keyParameters,
+ macAlg, key);
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ state->type = (retVal != 0) ? HASH_STATE_SMAC : HASH_STATE_EMPTY;
+ return retVal;
+}
+/* 10.2.20.2.2 CryptMacStart() */
+/* Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart() function because
+ of the difference in number of parameters. */
+UINT16
+CryptMacStart(
+ HMAC_STATE *state,
+ TPMU_PUBLIC_PARMS *keyParameters,
+ TPM_ALG_ID macAlg, // IN: the type of MAC
+ TPM2B *key
+ )
+{
+ MemorySet(state, 0, sizeof(HMAC_STATE));
+ if(CryptHashIsValidAlg(macAlg, FALSE))
+ {
+ return CryptHmacStart(state, macAlg, key->size, key->buffer);
+ }
+ else if(CryptSmacIsValidAlg(macAlg, FALSE))
+ {
+ return CryptSmacStart(&state->hashState, keyParameters, macAlg, key);
+ }
+ else
+ return 0;
+}
+/* 10.2.20.2.3 CryptMacEnd() */
+/* Dispatch to the MAC end function using a size and buffer pointer. */
+UINT16
+CryptMacEnd(
+ HMAC_STATE *state,
+ UINT32 size,
+ BYTE *buffer
+ )
+{
+ UINT16 retVal = 0;
+ if(state->hashState.type == HASH_STATE_SMAC)
+ retVal = (state->hashState.state.smac.smacMethods.end)(
+ &state->hashState.state.smac.state, size, buffer);
+ else if(state->hashState.type == HASH_STATE_HMAC)
+ retVal = CryptHmacEnd(state, size, buffer);
+ state->hashState.type = HASH_STATE_EMPTY;
+ return retVal;
+}
+#if 0 /* libtpms added */
+/* 10.2.20.2.4 CryptMacEnd2B() */
+/* Dispatch to the MAC end function using a 2B. */
+UINT16
+CryptMacEnd2B (
+ HMAC_STATE *state,
+ TPM2B *data
+ )
+{
+ return CryptMacEnd(state, data->size, data->buffer);
+}
+#endif /* libtpms added */
+#endif // SMAC_IMPLEMENTED
+
diff --git a/src/tpm2/crypto/openssl/CryptSym.c b/src/tpm2/crypto/openssl/CryptSym.c
new file mode 100644
index 0000000..c8a0497
--- /dev/null
+++ b/src/tpm2/crypto/openssl/CryptSym.c
@@ -0,0 +1,771 @@
+/********************************************************************************/
+/* */
+/* Symmetric block cipher modes */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: CryptSym.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 10.2.19 CryptSym.c */
+/* 10.2.19.1 Introduction */
+/* This file contains the implementation of the symmetric block cipher modes allowed for a
+ TPM. These functions only use the single block encryption functions of the selected symmetric
+ crypto library. */
+
+/* 10.2.19.2 Includes, Defines, and Typedefs */
+#include "Tpm.h"
+#include "CryptSym.h"
+#include "Helpers_fp.h" // libtpms changed
+
+
+#define KEY_BLOCK_SIZES(ALG, alg) \
+ static const INT16 alg##KeyBlockSizes[] = { \
+ ALG##_KEY_SIZES_BITS, -1, ALG##_BLOCK_SIZES };
+
+FOR_EACH_SYM(KEY_BLOCK_SIZES)
+
+/* 10.2.19.3 Initialization and Data Access Functions */
+/* 10.2.19.3.1 CryptSymInit() */
+/* This function is called to do _TPM_Init() processing */
+BOOL
+CryptSymInit(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.19.3.2 CryptSymStartup() */
+/* This function is called to do TPM2_Startup() processing */
+BOOL
+CryptSymStartup(
+ void
+ )
+{
+ return TRUE;
+}
+/* 10.2.20.4 Data Access Functions */
+/* 10.2.20.4.1 CryptGetSymmetricBlockSize() */
+/* This function returns the block size of the algorithm. The table of bit sizes has an entry for
+ each allowed key size. The entry for a key size is 0 if the TPM does not implement that key
+ size. The key size table is delimited with a negative number (-1). After the delimiter is a list
+ of block sizes with each entry corresponding to the key bit size. For most symmetric algorithms,
+ the block size is the same regardless of the key size but this arrangement allows them to be
+ different. */
+/* Return Values Meaning */
+/* <= 0 cipher not supported */
+/* > 0 the cipher block size in bytes */
+
+LIB_EXPORT INT16
+CryptGetSymmetricBlockSize(
+ TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm
+ UINT16 keySizeInBits // IN: the key size
+ )
+{
+ const INT16 *sizes;
+ INT16 i;
+#if 0 // libtpms added
+#define ALG_CASE(SYM, sym) case TPM_ALG_##SYM: sizes = sym##KeyBlockSizes; break
+#endif // libtpms added
+ switch(symmetricAlg)
+ {
+#define GET_KEY_BLOCK_POINTER(SYM, sym) \
+ case TPM_ALG_##SYM: \
+ sizes = sym##KeyBlockSizes; \
+ break;
+ // Get the pointer to the block size array
+ FOR_EACH_SYM(GET_KEY_BLOCK_POINTER);
+
+ default:
+ return 0;
+ }
+ // Find the index of the indicated keySizeInBits
+ for(i = 0; *sizes >= 0; i++, sizes++)
+ {
+ if(*sizes == keySizeInBits)
+ break;
+ }
+ // If sizes is pointing at the end of the list of key sizes, then the desired
+ // key size was not found so set the block size to zero.
+ if(*sizes++ < 0)
+ return 0;
+ // Advance until the end of the list is found
+ while(*sizes++ >= 0);
+ // sizes is pointing to the first entry in the list of block sizes. Use the
+ // ith index to find the block size for the corresponding key size.
+ return sizes[i];
+}
+
+#if !USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added
+/* 10.2.20.5 Symmetric Encryption */
+/* This function performs symmetric encryption based on the mode. */
+/* Error Returns Meaning */
+/* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
+/* TPM_RC_FAILURE Fatal error */
+LIB_EXPORT TPM_RC
+CryptSymmetricEncrypt(
+ BYTE *dOut, // OUT:
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ )
+{
+ BYTE *pIv;
+ int i;
+ BYTE tmp[MAX_SYM_BLOCK_SIZE];
+ BYTE *pT;
+ tpmCryptKeySchedule_t keySchedule;
+ INT16 blockSize;
+ TpmCryptSetSymKeyCall_t encrypt;
+ BYTE *iv;
+ BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
+ //
+ memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity
+ pAssert(dOut != NULL && key != NULL && dIn != NULL);
+ if(dSize == 0)
+ return TPM_RC_SUCCESS;
+ TEST(algorithm);
+ blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
+ if(blockSize == 0)
+ return TPM_RC_FAILURE;
+ // If the iv is provided, then it is expected to be block sized. In some cases,
+ // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
+ // with no knowledge of the actual block size. This function will set it.
+ if((ivInOut != NULL) && (mode != TPM_ALG_ECB))
+ {
+ ivInOut->t.size = blockSize;
+ iv = ivInOut->t.buffer;
+ }
+ else
+ iv = defaultIv;
+ pIv = iv;
+ // Create encrypt key schedule and set the encryption function pointer.
+ switch (algorithm)
+ {
+ FOR_EACH_SYM(ENCRYPT_CASE)
+
+ default:
+ return TPM_RC_SYMMETRIC;
+ }
+ switch(mode)
+ {
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the IV(counter)
+ ENCRYPT(&keySchedule, iv, tmp);
+ //increment the counter (counter is big-endian so start at end)
+ for(i = blockSize - 1; i >= 0; i--)
+ if((iv[i] += 1) != 0)
+ break;
+ // XOR the encrypted counter value with input and put into output
+ pT = tmp;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ *dOut++ = *dIn++ ^ *pT++;
+ }
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ // This is written so that dIn and dOut may be the same
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the "IV"
+ ENCRYPT(&keySchedule, iv, iv);
+ // XOR the encrypted IV into dIn to create the cipher text (dOut)
+ pIv = iv;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ *dOut++ = (*pIv++ ^ *dIn++);
+ }
+ break;
+#endif
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ // For CBC the data size must be an even multiple of the
+ // cipher block size
+ if((dSize % blockSize) != 0)
+ return TPM_RC_SIZE;
+ // XOR the data block into the IV, encrypt the IV into the IV
+ // and then copy the IV to the output
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ pIv = iv;
+ for(i = blockSize; i > 0; i--)
+ *pIv++ ^= *dIn++;
+ ENCRYPT(&keySchedule, iv, iv);
+ pIv = iv;
+ for(i = blockSize; i > 0; i--)
+ *dOut++ = *pIv++;
+ }
+ break;
+#endif
+ // CFB is not optional
+ case TPM_ALG_CFB:
+ // Encrypt the IV into the IV, XOR in the data, and copy to output
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the IV
+ ENCRYPT(&keySchedule, iv, iv);
+ pIv = iv;
+ for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ // XOR the data into the IV to create the cipher text
+ // and put into the output
+ *dOut++ = *pIv++ ^= *dIn++;
+ }
+ // If the inner loop (i loop) was smaller than blockSize, then dSize
+ // would have been smaller than blockSize and it is now negative. If
+ // it is negative, then it indicates how many bytes are needed to pad
+ // out the IV for the next round.
+ for(; dSize < 0; dSize++)
+ *pIv++ = 0;
+ break;
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ // For ECB the data size must be an even multiple of the
+ // cipher block size
+ if((dSize % blockSize) != 0)
+ return TPM_RC_SIZE;
+ // Encrypt the input block to the output block
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ ENCRYPT(&keySchedule, dIn, dOut);
+ dIn = &dIn[blockSize];
+ dOut = &dOut[blockSize];
+ }
+ break;
+#endif
+ default:
+ return TPM_RC_FAILURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+/* 10.2.20.5.1 CryptSymmetricDecrypt() */
+/* This function performs symmetric decryption based on the mode. */
+/* Error Returns Meaning */
+/* TPM_RC_FAILURE A fatal error */
+/* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
+LIB_EXPORT TPM_RC
+CryptSymmetricDecrypt(
+ BYTE *dOut, // OUT: decrypted data
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ )
+{
+ BYTE *pIv;
+ int i;
+ BYTE tmp[MAX_SYM_BLOCK_SIZE];
+ BYTE *pT;
+ tpmCryptKeySchedule_t keySchedule;
+ INT16 blockSize;
+ BYTE *iv;
+ TpmCryptSetSymKeyCall_t encrypt;
+ TpmCryptSetSymKeyCall_t decrypt;
+ BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
+
+ memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity
+ // These are used but the compiler can't tell because they are initialized
+ // in case statements and it can't tell if they are always initialized
+ // when needed, so... Comment these out if the compiler can tell or doesn't
+ // care that these are initialized before use.
+ encrypt = NULL;
+ decrypt = NULL;
+ pAssert(dOut != NULL && key != NULL && dIn != NULL);
+ if(dSize == 0)
+ return TPM_RC_SUCCESS;
+ TEST(algorithm);
+ blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
+ if(blockSize == 0)
+ return TPM_RC_FAILURE;
+ // If the iv is provided, then it is expected to be block sized. In some cases,
+ // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
+ // with no knowledge of the actual block size. This function will set it.
+ if((ivInOut != NULL) && (mode != TPM_ALG_ECB))
+ {
+ ivInOut->t.size = blockSize;
+ iv = ivInOut->t.buffer;
+ }
+ else
+ iv = defaultIv;
+ pIv = iv;
+ // Use the mode to select the key schedule to create. Encrypt always uses the
+ // encryption schedule. Depending on the mode, decryption might use either
+ // the decryption or encryption schedule.
+ switch(mode)
+ {
+#if ALG_CBC || ALG_ECB
+ case TPM_ALG_CBC: // decrypt = decrypt
+ case TPM_ALG_ECB:
+ // For ECB and CBC, the data size must be an even multiple of the
+ // cipher block size
+ if((dSize % blockSize) != 0)
+ return TPM_RC_SIZE;
+ switch (algorithm)
+ {
+ FOR_EACH_SYM(DECRYPT_CASE)
+ default:
+ return TPM_RC_SYMMETRIC;
+ }
+ break;
+#endif
+ default:
+ // For the remaining stream ciphers, use encryption to decrypt
+ switch (algorithm)
+ {
+ FOR_EACH_SYM(ENCRYPT_CASE)
+ default:
+ return TPM_RC_SYMMETRIC;
+ }
+ }
+ // Now do the mode-dependent decryption
+ switch(mode)
+ {
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ // Copy the input data to a temp buffer, decrypt the buffer into the
+ // output, XOR in the IV, and copy the temp buffer to the IV and repeat.
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ pT = tmp;
+ for(i = blockSize; i > 0; i--)
+ *pT++ = *dIn++;
+ DECRYPT(&keySchedule, tmp, dOut);
+ pIv = iv;
+ pT = tmp;
+ for(i = blockSize; i > 0; i--)
+ {
+ *dOut++ ^= *pIv;
+ *pIv++ = *pT++;
+ }
+ }
+ break;
+#endif
+ case TPM_ALG_CFB:
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the IV into the temp buffer
+ ENCRYPT(&keySchedule, iv, tmp);
+ pT = tmp;
+ pIv = iv;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ // Copy the current cipher text to IV, XOR
+ // with the temp buffer and put into the output
+ *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
+ }
+ // If the inner loop (i loop) was smaller than blockSize, then dSize
+ // would have been smaller than blockSize and it is now negative
+ // If it is negative, then it indicates how may fill bytes
+ // are needed to pad out the IV for the next round.
+ for(; dSize < 0; dSize++)
+ *pIv++ = 0;
+ break;
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the IV(counter)
+ ENCRYPT(&keySchedule, iv, tmp);
+ //increment the counter (counter is big-endian so start at end)
+ for(i = blockSize - 1; i >= 0; i--)
+ if((iv[i] += 1) != 0)
+ break;
+ // XOR the encrypted counter value with input and put into output
+ pT = tmp;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ *dOut++ = *dIn++ ^ *pT++;
+ }
+ break;
+#endif
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ DECRYPT(&keySchedule, dIn, dOut);
+ dIn = &dIn[blockSize];
+ dOut = &dOut[blockSize];
+ }
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ // This is written so that dIn and dOut may be the same
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the "IV"
+ ENCRYPT(&keySchedule, iv, iv);
+ // XOR the encrypted IV into dIn to create the cipher text (dOut)
+ pIv = iv;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ *dOut++ = (*pIv++ ^ *dIn++);
+ }
+ break;
+#endif
+ default:
+ return TPM_RC_FAILURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+#else // libtpms added begin
+
+#if ALG_TDES && ALG_CTR
+// Emulated TDES Counter mode since OpenSSL does not implement it
+static void TDES_CTR(const BYTE *key, // IN
+ INT32 keySizeInBits, // IN
+ INT32 dSize, // IN
+ const BYTE *dIn, // IN
+ BYTE *iv, // IN
+ BYTE *dOut, // OUT
+ INT16 blockSize // IN
+ )
+{
+ tpmCryptKeySchedule_t keySchedule;
+ int i;
+ BYTE tmp[MAX_SYM_BLOCK_SIZE];
+ BYTE *pT;
+
+ TDES_set_encrypt_key(key, keySizeInBits,
+ (tpmKeyScheduleTDES *)&keySchedule.tdes);
+
+ for(; dSize > 0; dSize -= blockSize)
+ {
+ // Encrypt the current value of the IV(counter)
+ TDES_encrypt(iv, tmp, (tpmKeyScheduleTDES *)&keySchedule.tdes);
+ //increment the counter (counter is big-endian so start at end)
+ for(i = blockSize - 1; i >= 0; i--)
+ if((iv[i] += 1) != 0)
+ break;
+ // XOR the encrypted counter value with input and put into output
+ pT = tmp;
+ for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
+ *dOut++ = *dIn++ ^ *pT++;
+ }
+}
+#endif
+
+/* 10.2.20.5 Symmetric Encryption */
+/* This function performs symmetric encryption based on the mode. */
+/* Error Returns Meaning */
+/* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
+/* TPM_RC_FAILURE Fatal error */
+LIB_EXPORT TPM_RC
+CryptSymmetricEncrypt(
+ BYTE *dOut, // OUT:
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ )
+{
+ INT16 blockSize;
+ BYTE *iv;
+ BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
+ evpfunc evpfn;
+ EVP_CIPHER_CTX *ctx = NULL;
+ int outlen1 = 0;
+ int outlen2 = 0;
+ BYTE *pOut = dOut;
+ BYTE *buffer = NULL; // for in-place encryption
+ UINT32 buffersize = 0;
+ BYTE keyToUse[MAX_SYM_KEY_BYTES];
+ UINT16 keyToUseLen = (UINT16)sizeof(keyToUse);
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ int ivLen;
+
+ pAssert(dOut != NULL && key != NULL && dIn != NULL);
+ if(dSize == 0)
+ return TPM_RC_SUCCESS;
+ TEST(algorithm);
+ blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
+ if(blockSize == 0)
+ return TPM_RC_FAILURE;
+ // If the iv is provided, then it is expected to be block sized. In some cases,
+ // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
+ // with no knowledge of the actual block size. This function will set it.
+ if((ivInOut != NULL) && (mode != TPM_ALG_ECB))
+ {
+ ivInOut->t.size = blockSize;
+ iv = ivInOut->t.buffer;
+ }
+ else
+ iv = defaultIv;
+
+ switch (mode)
+ {
+ case TPM_ALG_ECB:
+ case TPM_ALG_CBC:
+ // For ECB & CBC the data size must be an even multiple of the
+ // cipher block size
+ if((dSize % blockSize) != 0)
+ return TPM_RC_SIZE;
+ }
+
+ evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key,
+ keyToUse, &keyToUseLen);
+ if (evpfn == NULL)
+ return TPM_RC_FAILURE;
+
+ if (dIn == dOut) {
+ // in-place encryption; we use a temp buffer
+ buffersize = TPM2_ROUNDUP(dSize, blockSize);
+ buffer = malloc(buffersize);
+ if (buffer == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ pOut = buffer;
+ }
+
+#if ALG_TDES && ALG_CTR
+ if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) {
+ TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, pOut, blockSize);
+ outlen1 = dSize;
+ ERROR_RETURN(TPM_RC_SUCCESS);
+ }
+#endif
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx ||
+ EVP_EncryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 ||
+ EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 ||
+ EVP_EncryptUpdate(ctx, pOut, &outlen1, dIn, dSize) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ pAssert(outlen1 <= dSize || dSize >= outlen1 + blockSize);
+
+ if (EVP_EncryptFinal_ex(ctx, pOut + outlen1, &outlen2) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if (ivInOut) {
+ ivLen = EVP_CIPHER_CTX_iv_length(ctx);
+ if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer))
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ ivInOut->t.size = ivLen;
+ memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size);
+ }
+ Exit:
+ if (retVal == TPM_RC_SUCCESS && pOut != dOut)
+ memcpy(dOut, pOut, outlen1 + outlen2);
+
+ clear_and_free(buffer, buffersize);
+ EVP_CIPHER_CTX_free(ctx);
+
+ return retVal;
+}
+
+/* 10.2.20.5.1 CryptSymmetricDecrypt() */
+/* This function performs symmetric decryption based on the mode. */
+/* Error Returns Meaning */
+/* TPM_RC_FAILURE A fatal error */
+/* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
+LIB_EXPORT TPM_RC
+CryptSymmetricDecrypt(
+ BYTE *dOut, // OUT: decrypted data
+ TPM_ALG_ID algorithm, // IN: the symmetric algorithm
+ UINT16 keySizeInBits, // IN: key size in bits
+ const BYTE *key, // IN: key buffer. The size of this buffer
+ // in bytes is (keySizeInBits + 7) / 8
+ TPM2B_IV *ivInOut, // IN/OUT: IV for decryption.
+ TPM_ALG_ID mode, // IN: Mode to use
+ INT32 dSize, // IN: data size (may need to be a
+ // multiple of the blockSize)
+ const BYTE *dIn // IN: data buffer
+ )
+{
+ INT16 blockSize;
+ BYTE *iv;
+ BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
+ evpfunc evpfn;
+ EVP_CIPHER_CTX *ctx = NULL;
+ int outlen1 = 0;
+ int outlen2 = 0;
+ BYTE *buffer;
+ UINT32 buffersize = 0;
+ BYTE keyToUse[MAX_SYM_KEY_BYTES];
+ UINT16 keyToUseLen = (UINT16)sizeof(keyToUse);
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ int ivLen;
+
+ // These are used but the compiler can't tell because they are initialized
+ // in case statements and it can't tell if they are always initialized
+ // when needed, so... Comment these out if the compiler can tell or doesn't
+ // care that these are initialized before use.
+ pAssert(dOut != NULL && key != NULL && dIn != NULL);
+ if(dSize == 0)
+ return TPM_RC_SUCCESS;
+ TEST(algorithm);
+ blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
+ if(blockSize == 0)
+ return TPM_RC_FAILURE;
+ // If the iv is provided, then it is expected to be block sized. In some cases,
+ // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
+ // with no knowledge of the actual block size. This function will set it.
+ if((ivInOut != NULL) && (mode != TPM_ALG_ECB))
+ {
+ ivInOut->t.size = blockSize;
+ iv = ivInOut->t.buffer;
+ }
+ else
+ iv = defaultIv;
+
+ switch(mode)
+ {
+#if ALG_CBC || ALG_ECB
+ case TPM_ALG_CBC:
+ case TPM_ALG_ECB:
+ // For ECB and CBC, the data size must be an even multiple of the
+ // cipher block size
+ if((dSize % blockSize) != 0)
+ return TPM_RC_SIZE;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key,
+ keyToUse, &keyToUseLen);
+ if (evpfn == NULL)
+ return TPM_RC_FAILURE;
+
+ /* a buffer with a 'safety margin' for EVP_DecryptUpdate */
+ buffersize = TPM2_ROUNDUP(dSize + blockSize, blockSize);
+ buffer = malloc(buffersize);
+ if (buffer == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+#if ALG_TDES && ALG_CTR
+ if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) {
+ TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, buffer, blockSize);
+ outlen1 = dSize;
+ ERROR_RETURN(TPM_RC_SUCCESS);
+ }
+#endif
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx ||
+ EVP_DecryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 ||
+ EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 ||
+ EVP_DecryptUpdate(ctx, buffer, &outlen1, dIn, dSize) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ pAssert((int)buffersize >= outlen1);
+
+ if ((int)buffersize <= outlen1 /* coverity */ ||
+ EVP_DecryptFinal(ctx, &buffer[outlen1], &outlen2) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ pAssert((int)buffersize >= outlen1 + outlen2);
+
+ if (ivInOut) {
+ ivLen = EVP_CIPHER_CTX_iv_length(ctx);
+ if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer))
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ ivInOut->t.size = ivLen;
+ memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size);
+ }
+
+ Exit:
+ if (retVal == TPM_RC_SUCCESS) {
+ pAssert(dSize >= outlen1 + outlen2);
+ memcpy(dOut, buffer, outlen1 + outlen2);
+ }
+
+ clear_and_free(buffer, buffersize);
+ EVP_CIPHER_CTX_free(ctx);
+
+ return retVal;
+}
+
+#endif // libtpms added end
+
+/* 10.2.20.5.2 CryptSymKeyValidate() */
+/* Validate that a provided symmetric key meets the requirements of the TPM */
+/* Error Returns Meaning */
+/* TPM_RC_KEY_SIZE Key size specifiers do not match */
+/* TPM_RC_KEY Key is not allowed */
+TPM_RC
+CryptSymKeyValidate(
+ TPMT_SYM_DEF_OBJECT *symDef,
+ TPM2B_SYM_KEY *key
+ )
+{
+ if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym))
+ return TPM_RCS_KEY_SIZE;
+#if ALG_TDES
+ if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key))
+ return TPM_RCS_KEY;
+#endif // TPM_ALG_TDES
+ return TPM_RC_SUCCESS;
+}
diff --git a/src/tpm2/crypto/openssl/ExpDCache.c b/src/tpm2/crypto/openssl/ExpDCache.c
new file mode 100644
index 0000000..5aeaf14
--- /dev/null
+++ b/src/tpm2/crypto/openssl/ExpDCache.c
@@ -0,0 +1,200 @@
+/********************************************************************************/
+/* */
+/* Private Exponent D cache 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 (admin@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., 2021 */
+/* */
+/********************************************************************************/
+
+#include "Tpm.h"
+#include "ExpDCache_fp.h"
+
+/* Implement a cache for the private exponent D so it doesn't need to be
+ * recalculated every time from P, Q, E and N (modulus). The cache has a
+ * number of entries that cache D and use P, Q, and E for lookup.
+ * A least-recently-used cache eviction strategy is implemented that evicts
+ * the oldest cache entry in case space is needed. An entry is young once
+ * it is added or made young when it was found via lookup. All other entries
+ * age by '1' when an entry is added or accessed.
+ */
+
+struct ExpDCacheEntry {
+ /* The age of the entry; the higher the number the more likely it
+ * will be evicted soon
+ */
+ unsigned int age;
+ BIGNUM *P; /* input */
+ BIGNUM *N; /* input */
+ BIGNUM *E; /* input */
+ BIGNUM *Q; /* cached */
+ BIGNUM *D; /* cached */
+};
+
+#define DCACHE_NUM_ENTRIES 64
+
+static struct ExpDCacheEntry ExpDCache[DCACHE_NUM_ENTRIES];
+
+/* Increment the age of all cache entries that have a current age <= maxage */
+static void ExpDCacheIncrementAge(unsigned maxage)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) {
+ if (ExpDCache[i].age <= maxage && ExpDCache[i].D != NULL)
+ ExpDCache[i].age++;
+ }
+}
+
+/* Free the data associated with a ExpDCacheEntry and initialize it */
+static void ExpDCacheEntryFree(struct ExpDCacheEntry *dce)
+{
+ BN_clear_free(dce->P);
+ BN_free(dce->N);
+ BN_free(dce->E);
+ BN_clear_free(dce->Q);
+ BN_clear_free(dce->D);
+ memset(dce, 0, sizeof(*dce));
+}
+
+void ExpDCacheFree(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(ExpDCache); i++)
+ ExpDCacheEntryFree(&ExpDCache[i]);
+}
+
+/* Get a ExpDCacheEntry by finding either an unused entry or evicting the oldest
+ * entry. The returned entry will have all NULL pointers and age 0.
+ */
+static struct ExpDCacheEntry *ExpDCacheEntryGet(void)
+{
+ size_t i, use_i = 0;
+ unsigned oldest_age = 0;
+ struct ExpDCacheEntry *dce;
+
+ for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) {
+ if (ExpDCache[i].D == NULL) {
+ /* use this free entry */
+ use_i = i;
+ break;
+ }
+ if (ExpDCache[i].age > oldest_age) {
+ /* this one is currently the oldest */
+ use_i = i;
+ oldest_age = ExpDCache[i].age;
+ }
+ }
+ dce = &ExpDCache[use_i];
+
+ ExpDCacheEntryFree(dce);
+
+ return dce;
+}
+
+/* Add 'D' to the ExpDCache. This function does not check for duplicates */
+void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E,
+ const BIGNUM *Q, const BIGNUM *D)
+{
+ struct ExpDCacheEntry *dce = ExpDCacheEntryGet();
+
+ /* age of 'dce' is '0' */
+ dce->P = BN_dup(P);
+ dce->N = BN_dup(N);
+ dce->E = BN_dup(E);
+ dce->Q = BN_dup(Q);
+ dce->D = BN_dup(D);
+
+ if (!dce->P || !dce->N || !dce->E || !dce->Q || !dce->D)
+ ExpDCacheEntryFree(dce);
+ else
+ ExpDCacheIncrementAge(~0);
+}
+
+BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, BIGNUM **Q)
+{
+ size_t i;
+ unsigned myage;
+ BIGNUM *D;
+
+ for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) {
+ if (BN_cmp(ExpDCache[i].P, P) == 0 && BN_cmp(ExpDCache[i].N, N) == 0 &&
+ BN_cmp(ExpDCache[i].E, E) == 0) {
+ /* entry found */
+ myage = ExpDCache[i].age;
+ /* mark this entry as most recently used */
+ ExpDCache[i].age = 0;
+ /* Increment everyone who is <= 'myage'.
+ * The age of this entry will be '1' after that.
+ */
+ ExpDCacheIncrementAge(myage);
+
+ *Q = BN_dup(ExpDCache[i].Q);
+ if (*Q == NULL)
+ return NULL;
+ D = BN_dup(ExpDCache[i].D);
+ if (D == NULL) {
+ BN_clear_free(*Q);
+ *Q = NULL;
+ return NULL;
+ }
+ BN_set_flags(*Q, BN_FLG_CONSTTIME);
+ BN_set_flags(D, BN_FLG_CONSTTIME);
+ return D;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/tpm2/crypto/openssl/ExpDCache_fp.h b/src/tpm2/crypto/openssl/ExpDCache_fp.h
new file mode 100644
index 0000000..b8ee9d7
--- /dev/null
+++ b/src/tpm2/crypto/openssl/ExpDCache_fp.h
@@ -0,0 +1,75 @@
+/********************************************************************************/
+/* */
+/* Private Exponent D cache 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 (admin@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., 2021 */
+/* */
+/********************************************************************************/
+
+#ifndef DCACHE_FP_H
+#define DCACHE_FP_H
+
+#include <openssl/bn.h>
+
+BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E,
+ BIGNUM **Q);
+
+void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E,
+ const BIGNUM *Q, const BIGNUM *D);
+
+void ExpDCacheFree(void);
+
+#endif /* DCACHE_FP_H */
+
diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c
new file mode 100644
index 0000000..f47cdbf
--- /dev/null
+++ b/src/tpm2/crypto/openssl/Helpers.c
@@ -0,0 +1,625 @@
+/********************************************************************************/
+/* */
+/* OpenSSL 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 (admin@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, 2019 */
+/* */
+/********************************************************************************/
+
+#include "Tpm.h"
+#include "ExpDCache_fp.h"
+#include "Helpers_fp.h"
+#include "TpmToOsslMath_fp.h"
+
+#include "config.h"
+
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+
+/* to enable RSA_check_key() on private keys set to != 0 */
+#ifndef DO_RSA_CHECK_KEY
+#define DO_RSA_CHECK_KEY 0
+#endif
+
+#if USE_OPENSSL_FUNCTIONS_SYMMETRIC
+
+TPM_RC
+OpenSSLCryptGenerateKeyDes(
+ TPMT_SENSITIVE *sensitive // OUT: sensitive area
+ )
+{
+ DES_cblock *key;
+ size_t offset;
+ size_t limit;
+
+ limit = MIN(sizeof(sensitive->sensitive.sym.t.buffer),
+ sensitive->sensitive.sym.t.size);
+ limit = TPM2_ROUNDUP(limit, sizeof(*key));
+ pAssert(limit < sizeof(sensitive->sensitive.sym.t.buffer));
+
+ for (offset = 0; offset < limit; offset += sizeof(*key)) {
+ key = (DES_cblock *)&sensitive->sensitive.sym.t.buffer[offset];
+ if (DES_random_key(key) != 1)
+ return TPM_RC_NO_RESULT;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
+ UINT16 keySizeInBits, // IN
+ TPM_ALG_ID mode, // IN
+ const BYTE *key, // IN
+ BYTE *keyToUse, // OUT same as key or stretched key
+ UINT16 *keyToUseLen // IN/OUT
+ )
+{
+ int i;
+ UINT16 keySizeInBytes = keySizeInBits / 8;
+ evpfunc evpfn = NULL;
+
+ // key size to array index: 128 -> 0, 192 -> 1, 256 -> 2
+ i = (keySizeInBits >> 6) - 2;
+ if (i < 0 || i > 2)
+ return NULL;
+
+ pAssert(*keyToUseLen >= keySizeInBytes)
+ memcpy(keyToUse, key, keySizeInBytes);
+
+ switch (algorithm) {
+#if ALG_AES
+ case TPM_ALG_AES:
+ *keyToUseLen = keySizeInBytes;
+ switch (mode) {
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ evpfn = (evpfunc []){EVP_aes_128_ctr, EVP_aes_192_ctr,
+ EVP_aes_256_ctr}[i];
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ evpfn = (evpfunc[]){EVP_aes_128_ofb, EVP_aes_192_ofb,
+ EVP_aes_256_ofb}[i];
+ break;
+#endif
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ evpfn = (evpfunc[]){EVP_aes_128_cbc, EVP_aes_192_cbc,
+ EVP_aes_256_cbc}[i];
+ break;
+#endif
+#if ALG_CFB
+ case TPM_ALG_CFB:
+ evpfn = (evpfunc[]){EVP_aes_128_cfb, EVP_aes_192_cfb,
+ EVP_aes_256_cfb}[i];
+ break;
+#endif
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ evpfn = (evpfunc[]){EVP_aes_128_ecb, EVP_aes_192_ecb,
+ EVP_aes_256_ecb}[i];
+ break;
+#endif
+ }
+ break;
+#endif
+#if ALG_TDES
+ case TPM_ALG_TDES:
+ if (keySizeInBits == 128) {
+ pAssert(*keyToUseLen >= BITS_TO_BYTES(192))
+ // stretch the key
+ memcpy(&keyToUse[16], &keyToUse[0], 8);
+ *keyToUseLen = BITS_TO_BYTES(192);
+ }
+
+ switch (mode) {
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ evpfn = (evpfunc[]){EVP_des_ede3, EVP_des_ede3, NULL}[i];
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ evpfn = (evpfunc[]){EVP_des_ede3_ofb, EVP_des_ede3_ofb, NULL}[i];
+ break;
+#endif
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ evpfn = (evpfunc[]){EVP_des_ede3_cbc, EVP_des_ede3_cbc, NULL}[i];
+ break;
+#endif
+#if ALG_CFB
+ case TPM_ALG_CFB:
+ evpfn = (evpfunc[]){EVP_des_ede3_cfb64, EVP_des_ede3_cfb64, NULL}[i];
+ break;
+#endif
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ evpfn = (evpfunc[]){EVP_des_ede3_ecb, EVP_des_ede3_ecb, NULL}[i];
+ break;
+#endif
+ }
+ break;
+#endif
+
+#if ALG_SM4
+ case TPM_ALG_SM4:
+ *keyToUseLen = keySizeInBytes;
+ switch (mode) {
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ evpfn = (evpfunc[]){EVP_sm4_ctr, NULL, NULL}[i];
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ evpfn = (evpfunc[]){EVP_sm4_ofb, NULL, NULL}[i];
+ break;
+#endif
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ evpfn = (evpfunc[]){EVP_sm4_cbc, NULL, NULL}[i];
+ break;
+#endif
+#if ALG_CFB
+ case TPM_ALG_CFB:
+ evpfn = (evpfunc[]){EVP_sm4_cfb, NULL, NULL}[i];
+ break;
+#endif
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ evpfn = (evpfunc[]){EVP_sm4_ecb, NULL, NULL}[i];
+ break;
+#endif
+ }
+ break;
+#endif
+
+#if ALG_CAMELLIA
+ case TPM_ALG_CAMELLIA:
+ *keyToUseLen = keySizeInBytes;
+ switch (mode) {
+#if ALG_CTR
+ case TPM_ALG_CTR:
+ evpfn = (evpfunc []){EVP_camellia_128_ctr, EVP_camellia_192_ctr,
+ EVP_camellia_256_ctr}[i];
+ break;
+#endif
+#if ALG_OFB
+ case TPM_ALG_OFB:
+ evpfn = (evpfunc[]){EVP_camellia_128_ofb, EVP_camellia_192_ofb,
+ EVP_camellia_256_ofb}[i];
+ break;
+#endif
+#if ALG_CBC
+ case TPM_ALG_CBC:
+ evpfn = (evpfunc[]){EVP_camellia_128_cbc, EVP_camellia_192_cbc,
+ EVP_camellia_256_cbc}[i];
+ break;
+#endif
+#if ALG_CFB
+ case TPM_ALG_CFB:
+ evpfn = (evpfunc[]){EVP_camellia_128_cfb, EVP_camellia_192_cfb,
+ EVP_camellia_256_cfb}[i];
+ break;
+#endif
+#if ALG_ECB
+ case TPM_ALG_ECB:
+ evpfn = (evpfunc[]){EVP_camellia_128_ecb, EVP_camellia_192_ecb,
+ EVP_camellia_256_ecb}[i];
+ break;
+#endif
+ }
+ break;
+#endif
+ }
+
+ if (evpfn == NULL)
+ MemorySet(keyToUse, 0, *keyToUseLen);
+
+ return evpfn;
+}
+
+#endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC
+
+#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 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);
+
+ if (!eckey)
+ return FALSE;
+
+ if (EC_KEY_set_group(eckey, G) != 1)
+ goto Exit;
+
+ 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:
+ EC_KEY_free(eckey);
+
+ return OK;
+}
+#endif // USE_OPENSSL_FUNCTIONS_EC
+
+#if USE_OPENSSL_FUNCTIONS_RSA
+
+static const struct hnames {
+ const char *name;
+ TPM_ALG_ID hashAlg;
+} hnames[HASH_COUNT + 1] = {
+ {
+#if ALG_SHA1
+ .name = "sha1",
+ .hashAlg = ALG_SHA1_VALUE,
+ }, {
+#endif
+#if ALG_SHA256
+ .name = "sha256",
+ .hashAlg = ALG_SHA256_VALUE,
+ }, {
+#endif
+#if ALG_SHA384
+ .name = "sha384",
+ .hashAlg = ALG_SHA384_VALUE,
+ }, {
+#endif
+#if ALG_SHA512
+ .name = "sha512",
+ .hashAlg = ALG_SHA512_VALUE,
+ }, {
+#endif
+ .name = NULL,
+ }
+};
+#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512
+# error Missing entry in hnames array!
+#endif
+
+LIB_EXPORT const char *
+GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg)
+{
+ unsigned i;
+
+ for (i = 0; i < HASH_COUNT; i++) {
+ if (hashAlg == hnames[i].hashAlg)
+ return hnames[i].name;
+ }
+ return NULL;
+}
+
+static BOOL
+ComputePrivateExponentD(
+ const BIGNUM *P, // IN: first prime (size is 1/2 of bnN)
+ const BIGNUM *Q, // IN: second prime (size is 1/2 of bnN)
+ const BIGNUM *E, // IN: the public exponent
+ const BIGNUM *N, // IN: the public modulus
+ BIGNUM **D // OUT:
+ )
+{
+ BOOL pOK = FALSE;
+ BIGNUM *phi;
+ BN_CTX *ctx;
+ //
+ // compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1
+ phi = BN_dup(N);
+ ctx = BN_CTX_new();
+ if (phi && ctx) {
+ pOK = BN_sub(phi, phi, P);
+ 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); // phi is secret
+ pOK = pOK && (*D = BN_mod_inverse(NULL, E, phi, ctx)) != NULL;
+ }
+ BN_CTX_free(ctx);
+ BN_clear_free(phi);
+
+ return pOK;
+}
+
+LIB_EXPORT TPM_RC
+InitOpenSSLRSAPublicKey(OBJECT *key, // IN
+ EVP_PKEY **pkey // OUT
+ )
+{
+ TPM_RC retVal;
+ RSA *rsakey = RSA_new();
+ BIGNUM *N = NULL;
+ BIGNUM *E = BN_new();
+ BN_ULONG eval;
+
+ *pkey = EVP_PKEY_new();
+
+ if (rsakey == NULL || *pkey == NULL || E == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ if(key->publicArea.parameters.rsaDetail.exponent != 0)
+ eval = key->publicArea.parameters.rsaDetail.exponent;
+ else
+ eval = RSA_DEFAULT_PUBLIC_EXPONENT;
+
+ if (BN_set_word(E, eval) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ N = BN_bin2bn(key->publicArea.unique.rsa.b.buffer,
+ key->publicArea.unique.rsa.b.size, NULL);
+ if (N == NULL ||
+ RSA_set0_key(rsakey, N, E, NULL) != 1 ||
+ EVP_PKEY_assign_RSA(*pkey, rsakey) == 0)
+ ERROR_RETURN(TPM_RC_FAILURE)
+
+ RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING);
+
+ retVal = TPM_RC_SUCCESS;
+
+ Exit:
+ if (retVal != TPM_RC_SUCCESS) {
+ RSA_free(rsakey);
+ EVP_PKEY_free(*pkey);
+ *pkey = NULL;
+ }
+
+ return retVal;
+}
+
+static void DoRSACheckKey(const BIGNUM *P, const BIGNUM *Q, const BIGNUM *N,
+ const BIGNUM *E, const BIGNUM *D)
+{
+ RSA *mykey;
+ static int disp;
+
+ if (!DO_RSA_CHECK_KEY)
+ return;
+ if (!disp) {
+ fprintf(stderr, "RSA key checking is enabled\n");
+ disp = 1;
+ }
+
+ mykey = RSA_new();
+ RSA_set0_factors(mykey, BN_dup(P), BN_dup(Q));
+ RSA_set0_key(mykey, BN_dup(N), BN_dup(E), BN_dup(D));
+ if (RSA_check_key(mykey) != 1) {
+ fprintf(stderr, "Detected bad RSA key. STOP.\n");
+ while (1);
+ }
+ RSA_free(mykey);
+}
+
+LIB_EXPORT TPM_RC
+InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN
+ EVP_PKEY **pkey // OUT
+ )
+{
+ const BIGNUM *N = NULL;
+ const BIGNUM *E = NULL;
+ BIGNUM *P = NULL;
+ BIGNUM *Q = NULL;
+ BIGNUM *Qr = NULL;
+ BIGNUM *D = NULL;
+#if CRT_FORMAT_RSA == YES
+ BIGNUM *dP = BN_new();
+ BIGNUM *dQ = BN_new();
+ BIGNUM *qInv = BN_new();
+#endif
+ RSA *key = NULL;
+ BN_CTX *ctx = NULL;
+ TPM_RC retVal = InitOpenSSLRSAPublicKey(rsaKey, pkey);
+
+ if (retVal != TPM_RC_SUCCESS)
+ return retVal;
+
+ if(!rsaKey->attributes.privateExp)
+ CryptRsaLoadPrivateExponent(rsaKey);
+
+ P = BN_bin2bn(rsaKey->sensitive.sensitive.rsa.t.buffer,
+ rsaKey->sensitive.sensitive.rsa.t.size, NULL);
+ if (P == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE)
+
+ key = EVP_PKEY_get1_RSA(*pkey);
+ if (key == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ RSA_get0_key(key, &N, &E, NULL);
+
+ D = ExpDCacheFind(P, N, E, &Q);
+ if (D == NULL) {
+ ctx = BN_CTX_new();
+ Q = BN_new();
+ Qr = BN_new();
+ if (ctx == NULL || Q == NULL || Qr == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ /* 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
+
+ if (ComputePrivateExponentD(P, Q, E, N, &D) == FALSE)
+ ERROR_RETURN(TPM_RC_FAILURE);
+ ExpDCacheAdd(P, N, E, Q, D);
+ }
+ if (RSA_set0_key(key, NULL, NULL, D) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ DoRSACheckKey(P, Q, N, E, D);
+
+ D = NULL;
+
+#if CRT_FORMAT_RSA == YES
+ /* CRT parameters are not absolutely needed but may speed up ops */
+ dP = BigInitialized(dP, (bigConst)&rsaKey->privateExponent.dP);
+ dQ = BigInitialized(dQ, (bigConst)&rsaKey->privateExponent.dQ);
+ qInv = BigInitialized(qInv, (bigConst)&rsaKey->privateExponent.qInv);
+ if (dP == NULL || dQ == NULL || qInv == NULL ||
+ RSA_set0_crt_params(key, dP, dQ, qInv) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+#endif
+
+ retVal = TPM_RC_SUCCESS;
+
+ Exit:
+ BN_CTX_free(ctx);
+ BN_clear_free(P);
+ BN_clear_free(Q);
+ BN_free(Qr);
+ RSA_free(key); // undo reference from EVP_PKEY_get1_RSA()
+
+ if (retVal != TPM_RC_SUCCESS) {
+ BN_clear_free(D);
+#if CRT_FORMAT_RSA == YES
+ BN_clear_free(dP);
+ BN_clear_free(dQ);
+ BN_clear_free(qInv);
+#endif
+ EVP_PKEY_free(*pkey);
+ *pkey = NULL;
+ }
+
+ return retVal;
+}
+
+LIB_EXPORT TPM_RC
+OpenSSLCryptRsaGenerateKey(
+ OBJECT *rsaKey, // IN/OUT: The object structure in which
+ // the key is created.
+ UINT32 e,
+ int keySizeInBits
+ )
+{
+ TPMT_PUBLIC *publicArea = &rsaKey->publicArea;
+ TPMT_SENSITIVE *sensitive = &rsaKey->sensitive;
+ TPM_RC retVal = TPM_RC_SUCCESS;
+ int rc;
+ RSA *rsa = NULL;
+ const BIGNUM *bnP = NULL;
+ const BIGNUM *bnN = NULL;
+ BIGNUM *bnE = BN_new();
+ BN_RSA(tmp);
+
+ if (bnE == NULL || BN_set_word(bnE, e) != 1)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ // Need to initialize the privateExponent structure
+ RsaInitializeExponent(&rsaKey->privateExponent);
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ ERROR_RETURN(TPM_RC_FAILURE);
+
+ rc = RSA_generate_key_ex(rsa, keySizeInBits, bnE, NULL);
+ if (rc == 0)
+ ERROR_RETURN(TPM_RC_NO_RESULT);
+
+ RSA_get0_key(rsa, &bnN, NULL, NULL);
+ RSA_get0_factors(rsa, &bnP, NULL);
+
+ OsslToTpmBn(tmp, bnN);
+ BnTo2B((bigNum)tmp, &publicArea->unique.rsa.b, 0);
+
+ OsslToTpmBn(tmp, bnP);
+ BnTo2B((bigNum)tmp, &sensitive->sensitive.rsa.b, 0);
+
+ // CryptRsaGenerateKey calls ComputePrivateExponent; we have to call
+ // it via CryptRsaLoadPrivateExponent
+ retVal = CryptRsaLoadPrivateExponent(rsaKey);
+
+ Exit:
+ BN_free(bnE);
+ RSA_free(rsa);
+
+ return retVal;
+}
+
+#endif // USE_OPENSSL_FUNCTIONS_RSA
diff --git a/src/tpm2/crypto/openssl/Helpers_fp.h b/src/tpm2/crypto/openssl/Helpers_fp.h
new file mode 100644
index 0000000..5b9ca14
--- /dev/null
+++ b/src/tpm2/crypto/openssl/Helpers_fp.h
@@ -0,0 +1,117 @@
+/********************************************************************************/
+/* */
+/* OpenSSL 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 (admin@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, 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef HELPERS_FP_H
+#define HELPERS_FP_H
+
+#include "TpmTypes.h"
+
+#include <openssl/evp.h>
+
+#if USE_OPENSSL_FUNCTIONS_SYMMETRIC
+TPM_RC
+OpenSSLCryptGenerateKeyDes(
+ TPMT_SENSITIVE *sensitive // OUT: sensitive area
+ );
+
+typedef const EVP_CIPHER *(*evpfunc)(void);
+
+evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN
+ UINT16 keySizeInBits, // IN
+ TPM_ALG_ID mode, // IN
+ const BYTE *key, // IN
+ BYTE *keyToUse, // OUT same as key or stretched key
+ UINT16 *keyToUseLen // IN/OUT
+ );
+#endif
+
+#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 UINT32 requestedBits // IN: if not 0, then dOut must have that many bits
+ );
+#endif
+
+#if USE_OPENSSL_FUNCTIONS_RSA
+
+const char *GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg);
+
+LIB_EXPORT TPM_RC
+OpenSSLCryptRsaGenerateKey(
+ OBJECT *rsaKey, // IN/OUT: The object structure in which
+ // the key is created.
+ UINT32 e,
+ int keySizeInBits
+ );
+
+LIB_EXPORT TPM_RC
+InitOpenSSLRSAPublicKey(OBJECT *key, // IN
+ EVP_PKEY **pkey //OUT
+ );
+
+LIB_EXPORT TPM_RC
+InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN
+ EVP_PKEY **pkey // OUT
+ );
+
+#endif // USE_OPENSSL_FUNCTIONS_RSA
+
+#endif /* HELPERS_FP_H */
diff --git a/src/tpm2/crypto/openssl/LibSupport.h b/src/tpm2/crypto/openssl/LibSupport.h
new file mode 100644
index 0000000..d571b84
--- /dev/null
+++ b/src/tpm2/crypto/openssl/LibSupport.h
@@ -0,0 +1,98 @@
+/********************************************************************************/
+/* */
+/* select the library code that gets included in the TPM build */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: LibSupport.h 1656 2021-01-15 21:45:18Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+// 5.12 LibSupport.h
+// This header file is used to select the library code that gets included in the TPM build
+#ifndef _LIB_SUPPORT_H_
+#define _LIB_SUPPORT_H_
+
+#if 0 // libtpms added
+/* kgold added power and s390 */
+#ifndef RADIX_BITS
+# if defined(__x86_64__) || defined(__x86_64) \
+ || defined(__amd64__) || defined(__amd64) \
+ || defined(_WIN64) || defined(_M_X64) \
+ || defined(_M_ARM64) || defined(__aarch64__) \
+ || defined(__powerpc64__) || defined(__PPC64__) || defined(__ppc64__) \
+ || defined(__s390x__)
+# define RADIX_BITS 64
+# elif defined(__i386__) || defined(__i386) || defined(i386) \
+ || defined(_WIN32) || defined(_M_IX86) \
+ || defined(_M_ARM) || defined(__arm__) || defined(__thumb__) \
+ || defined(__powerpc__) || defined(__PPC__)
+# define RADIX_BITS 32
+# else
+# error Unable to determine RADIX_BITS from compiler environment
+# endif
+#endif // RADIX_BITS
+#endif // libtpms added
+
+// These macros use the selected libraries to the proper include files.
+#define LIB_QUOTE(_STRING_) #_STRING_
+#define LIB_INCLUDE2(_LIB_, _TYPE_) LIB_QUOTE(TpmTo##_LIB_##_TYPE_.h)
+#define LIB_INCLUDE(_LIB_, _TYPE_) LIB_INCLUDE2(_LIB_, _TYPE_)
+// Include the options for hashing and symmetric. Defer the load of the math package until the
+// bignum parameters are defined.
+#include LIB_INCLUDE(SYM_LIB, Sym)
+#include LIB_INCLUDE(HASH_LIB, Hash)
+#undef MIN
+#undef MAX
+#endif // _LIB_SUPPORT_H_
diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c
new file mode 100644
index 0000000..d27aad2
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c
@@ -0,0 +1,119 @@
+/********************************************************************************/
+/* */
+/* TPM DES Support */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslDesSupport.c 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+/* B.2.3.1. TpmToOsslDesSupport.c */
+/* B.2.3.1.1. Introduction */
+/* The functions in this file are used for initialization of the interface to the OpenSSL
+ library. */
+/* B.2.3.1.2. Defines and Includes */
+#include "Tpm.h"
+#if (defined SYM_LIB_OSSL) && ALG_TDES
+/* B.2.3.1.3. Functions */
+/* B.2.3.1.3.1. TDES_set_encyrpt_key() */
+/* This function makes creation of a TDES key look like the creation of a key for any of the other
+ OpenSSL block ciphers. It will create three key schedules, one for each of the DES keys. If
+ there are only two keys, then the third schedule is a copy of the first. */
+void
+TDES_set_encrypt_key(
+ const BYTE *key,
+ UINT16 keySizeInBits,
+ tpmKeyScheduleTDES *keySchedule
+ )
+{
+ DES_set_key_unchecked((const_DES_cblock *)key, &keySchedule[0]);
+ DES_set_key_unchecked((const_DES_cblock *)&key[8], &keySchedule[1]);
+ // If is two-key, copy the schedule for K1 into K3, otherwise, compute the
+ // the schedule for K3
+ if(keySizeInBits == 128)
+ keySchedule[2] = keySchedule[0];
+ else
+ DES_set_key_unchecked((const_DES_cblock *)&key[16],
+ &keySchedule[2]);
+}
+/* B.2.3.1.3.2. TDES_encyrpt() */
+/* The TPM code uses one key schedule. For TDES, the schedule contains three schedules. OpenSSL
+ wants the schedules referenced separately. This function does that. */
+void TDES_encrypt(
+ const BYTE *in,
+ BYTE *out,
+ tpmKeyScheduleTDES *ks
+ )
+{
+ DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out,
+ &ks[0], &ks[1], &ks[2],
+ DES_ENCRYPT);
+}
+#if !USE_OPENSSL_FUNCTIONS_SYMMETRIC
+/* B.2.3.1.3.3. TDES_decrypt() */
+/* As with TDES_encypt() this function bridges between the TPM single schedule model and the
+ OpenSSL three schedule model. */
+void TDES_decrypt(
+ const BYTE *in,
+ BYTE *out,
+ tpmKeyScheduleTDES *ks
+ )
+{
+ DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out,
+ &ks[0], &ks[1], &ks[2],
+ DES_DECRYPT);
+}
+#endif // !USE_OPENSSL_FUNCTIONS_SYMMETRIC
+#endif // SYM_LIB_OSSL
diff --git a/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h
new file mode 100644
index 0000000..4338fe6
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h
@@ -0,0 +1,83 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslDesSupport_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 */
+/* */
+/********************************************************************************/
+
+#ifndef TPMTOOSSLDESSUPPORT_FP_H
+#define TPMTOOSSLDESSUPPORT_FP_H
+
+void
+TDES_set_encrypt_key(
+ const BYTE *key,
+ UINT16 keySizeInBits,
+ tpmKeyScheduleTDES *keySchedule
+ );
+void TDES_encrypt(
+ const BYTE *in,
+ BYTE *out,
+ tpmKeyScheduleTDES *ks
+ );
+void TDES_decrypt(
+ const BYTE *in,
+ BYTE *out,
+ tpmKeyScheduleTDES *ks
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/openssl/TpmToOsslHash.h b/src/tpm2/crypto/openssl/TpmToOsslHash.h
new file mode 100644
index 0000000..9fa6479
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslHash.h
@@ -0,0 +1,219 @@
+/********************************************************************************/
+/* */
+/* Used to splice the OpenSSL() hash code into the TPM code */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* B.2.2.1. TpmToOsslHash.h */
+/* B.2.2.1.1. Introduction */
+/* This header file is used to splice the OpenSSL hash code into the TPM code. */
+#ifndef HASH_LIB_DEFINED
+#define HASH_LIB_DEFINED
+#define HASH_LIB_OSSL
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#if ALG_SM3_256
+# if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L
+# if ALG_SM3_256 // libtpms added begin
+# error This version of OpenSSL does not support SM3
+# endif // libtpms added end
+# undef ALG_SM3_256
+# define ALG_SM3_256 ALG_NO
+# elif OPENSSL_VERSION_NUMBER >= 0x10200000L
+# include <openssl/sm3.h>
+# else
+// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory,
+// and they do not get installed as part of the libssl package
+# define SM3_LBLOCK (64/4)
+
+# error Check support for this version of SM3 in OpenSSL (libtpms)
+typedef struct SM3state_st {
+ unsigned int A, B, C, D, E, F, G, H;
+ unsigned int Nl, Nh;
+ unsigned int data[SM3_LBLOCK];
+ unsigned int num;
+} SM3_CTX;
+
+int sm3_init(SM3_CTX *c);
+int sm3_update(SM3_CTX *c, const void *data, size_t len);
+int sm3_final(unsigned char *md, SM3_CTX *c);
+# endif // OpenSSL < 1.2
+#endif // ALG_SM3_256
+
+#include <openssl/ossl_typ.h>
+
+#define HASH_ALIGNMENT RADIX_BYTES /* libtpms: keep; not sure whether needed */
+
+/* B.2.2.1.2. Links to the OpenSSL HASH code */
+/* Redefine the internal name used for each of the hash state structures to the name used by the
+ library. These defines need to be known in all parts of the TPM so that the structure sizes can
+ be properly computed when needed. */
+#define tpmHashStateSHA1_t SHA_CTX
+#define tpmHashStateSHA256_t SHA256_CTX
+#define tpmHashStateSHA384_t SHA512_CTX
+#define tpmHashStateSHA512_t SHA512_CTX
+#define tpmHashStateSM3_256_t SM3_CTX
+#if ALG_SM3_256
+# error "The version of OpenSSL used by this code does not support SM3"
+#endif
+/* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation
+ is primarily to avoid name space collision. However, if there is a real collision, it will
+ likely show up when the linker tries to put things together. */
+#ifdef _CRYPT_HASH_C_
+typedef BYTE *PBYTE;
+typedef const BYTE *PCBYTE;
+/* Define the interface between CryptHash.c to the functions provided by the library. For each
+ method, define the calling parameters of the method and then define how the method is invoked in
+ CryptHash.c. */
+/* All hashes are required to have the same calling sequence. If they don't, create a simple
+ adaptation function that converts from the standard form of the call to the form used by the
+ specific hash (and then send a nasty letter to the person who wrote the hash function for the
+ library). */
+/* The macro that calls the method also defines how the parameters get swizzled between the default
+ form (in CryptHash.c)and the library form. */
+
+#define HASH_ALIGNMENT RADIX_BYTES
+
+/* Initialize the hash context */
+#define HASH_START_METHOD_DEF void (HASH_START_METHOD)(PANY_HASH_STATE state)
+#define HASH_START(hashState) \
+ ((hashState)->def->method.start)(&(hashState)->state);
+/* Add data to the hash */
+#define HASH_DATA_METHOD_DEF \
+ void (HASH_DATA_METHOD)(PANY_HASH_STATE state, \
+ PCBYTE buffer, \
+ size_t size)
+#define HASH_DATA(hashState, dInSize, dIn) \
+ ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize)
+/* Finalize the hash and get the digest */
+#define HASH_END_METHOD_DEF \
+ void (HASH_END_METHOD)(BYTE *buffer, PANY_HASH_STATE state)
+#define HASH_END(hashState, buffer) \
+ ((hashState)->def->method.end)(buffer, &(hashState)->state)
+/* Copy the hash context */
+/* NOTE: For import, export, and copy, memcpy() is used since there is no reformatting necessary
+ between the internal and external forms. */
+#define HASH_STATE_COPY_METHOD_DEF \
+ void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to, \
+ PCANY_HASH_STATE from, \
+ size_t size)
+#define HASH_STATE_COPY(hashStateOut, hashStateIn) \
+ ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \
+ &(hashStateIn)->state, \
+ (hashStateIn)->def->contextSize)
+/* Copy (with reformatting when necessary) an internal hash structure to an external blob */
+#define HASH_STATE_EXPORT_METHOD_DEF \
+ void (HASH_STATE_EXPORT_METHOD)(BYTE *to, \
+ PCANY_HASH_STATE from, \
+ size_t size)
+#define HASH_STATE_EXPORT(to, hashStateFrom) \
+ ((hashStateFrom)->def->method.copyOut) \
+ (&(((BYTE *)(to))[offsetof(HASH_STATE, state)]), \
+ &(hashStateFrom)->state, \
+ (hashStateFrom)->def->contextSize)
+/* Copy from an external blob to an internal format (with reformatting when necessary) */
+#define HASH_STATE_IMPORT_METHOD_DEF \
+ void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, \
+ const BYTE *from, \
+ size_t size)
+#define HASH_STATE_IMPORT(hashStateTo, from) \
+ ((hashStateTo)->def->method.copyIn) \
+ (&(hashStateTo)->state, \
+ &(((const BYTE *)(from))[offsetof(HASH_STATE, state)]), \
+ (hashStateTo)->def->contextSize)
+/* Function aliases. The code in CryptHash.c uses the internal designation for the functions. These
+ need to be translated to the function names of the library. */
+#define tpmHashStart_SHA1 SHA1_Init // external name of the initialization method
+#define tpmHashData_SHA1 SHA1_Update
+#define tpmHashEnd_SHA1 SHA1_Final
+#define tpmHashStateCopy_SHA1 memcpy
+#define tpmHashStateExport_SHA1 memcpy
+#define tpmHashStateImport_SHA1 memcpy
+#define tpmHashStart_SHA256 SHA256_Init
+#define tpmHashData_SHA256 SHA256_Update
+#define tpmHashEnd_SHA256 SHA256_Final
+#define tpmHashStateCopy_SHA256 memcpy
+#define tpmHashStateExport_SHA256 memcpy
+#define tpmHashStateImport_SHA256 memcpy
+#define tpmHashStart_SHA384 SHA384_Init
+#define tpmHashData_SHA384 SHA384_Update
+#define tpmHashEnd_SHA384 SHA384_Final
+#define tpmHashStateCopy_SHA384 memcpy
+#define tpmHashStateExport_SHA384 memcpy
+#define tpmHashStateImport_SHA384 memcpy
+#define tpmHashStart_SHA512 SHA512_Init
+#define tpmHashData_SHA512 SHA512_Update
+#define tpmHashEnd_SHA512 SHA512_Final
+#define tpmHashStateCopy_SHA512 memcpy
+#define tpmHashStateExport_SHA512 memcpy
+#define tpmHashStateImport_SHA512 memcpy
+#define tpmHashStart_SM3_256 sm3_init
+#define tpmHashData_SM3_256 sm3_update
+#define tpmHashEnd_SM3_256 sm3_final
+#define tpmHashStateCopy_SM3_256 memcpy
+#define tpmHashStateExport_SM3_256 memcpy
+#define tpmHashStateImport_SM3_256 memcpy
+
+#endif // _CRYPT_HASH_C_
+#define LibHashInit()
+/* This definition would change if there were something to report */
+#define HashLibSimulationEnd()
+#endif // // HASH_LIB_DEFINED
+
+
diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath.c b/src/tpm2/crypto/openssl/TpmToOsslMath.c
new file mode 100644
index 0000000..18e6c23
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslMath.c
@@ -0,0 +1,736 @@
+/********************************************************************************/
+/* */
+/* TPM to OpenSSL BigNum Shim Layer */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslMath.c 1598 2020-03-27 21:59:49Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+/* B.2.3.2. TpmToOsslMath.c */
+/* B.2.3.2.1. Introduction */
+
+/* The functions in this file provide the low-level interface between the TPM code and the big
+ number and elliptic curve math routines in OpenSSL. */
+/* Most math on big numbers require a context. The context contains the memory in which OpenSSL
+ creates and manages the big number values. When a OpenSSL math function will be called that
+ modifies a BIGNUM value, that value must be created in an OpenSSL context. The first line of code
+ in such a function must be: OSSL_ENTER(); and the last operation before returning must be
+ OSSL_LEAVE(). OpenSSL variables can then be created with BnNewVariable(). Constant values to be
+ used by OpenSSL are created from the bigNum values passed to the functions in this file. Space
+ for the BIGNUM control block is allocated in the stack of the function and then it is initialized
+ by calling BigInitialized(). That function sets up the values in the BIGNUM structure and sets
+ the data pointer to point to the data in the bignum_t. This is only used when the value is known
+ to be a constant in the called function. */
+/* Because the allocations of constants is on the local stack and the OSSL_ENTER()/OSSL_LEAVE() pair
+ flushes everything created in OpenSSL memory, there should be no chance of a memory leak. */
+
+
+#include "Tpm.h"
+#ifdef MATH_LIB_OSSL
+#include "TpmToOsslMath_fp.h"
+
+/* B.2.3.2.3.1. OsslToTpmBn() */
+/* This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation it is assumed
+ that OpenSSL uses a different control structure but the same data layout -- an array of
+ native-endian words in little-endian order. */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure because value will not fit or OpenSSL variable doesn't exist */
+BOOL
+OsslToTpmBn(
+ bigNum bn,
+ const BIGNUM *osslBn // libtpms: added 'const'
+ )
+{
+ VERIFY(osslBn != NULL);
+ // If the bn is NULL, it means that an output value pointer was NULL meaning that
+ // the results is simply to be discarded.
+ unsigned char buffer[LARGEST_NUMBER + 1]; // libtpms added
+ int buffer_len; // libtpms added
+
+ if(bn != NULL)
+ {
+#if 1 //libtpms added begin
+ int num_bytes;
+
+ num_bytes = BN_num_bytes(osslBn);
+ VERIFY(num_bytes >= 0 && sizeof(buffer) >= (size_t)num_bytes);
+ buffer_len = BN_bn2bin(osslBn, buffer); /* ossl to bin */
+ BnFromBytes(bn, buffer, buffer_len); /* bin to TPM */
+#else // libtpms added end
+ int i;
+ //
+ VERIFY((unsigned)osslBn->top <= BnGetAllocated(bn));
+ for(i = 0; i < osslBn->top; i++)
+ bn->d[i] = osslBn->d[i];
+ BnSetTop(bn, osslBn->top);
+#endif // libtpms added
+ }
+ return TRUE;
+ Error:
+ return FALSE;
+}
+
+/* B.2.3.2.3.2. BigInitialized() */
+/* This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for values that are
+ passed to OpenSLL when they are not declared as const in the function prototype. Instead, use
+ BnNewVariable(). */
+BIGNUM *
+BigInitialized(
+ BIGNUM *toInit,
+ bigConst initializer
+ )
+{
+#if 1 // libtpms added begin
+ BIGNUM *_toInit;
+ unsigned char buffer[LARGEST_NUMBER + 1];
+ NUMBYTES buffer_len = (NUMBYTES )sizeof(buffer);
+#endif // libtpms added end
+
+ if(initializer == NULL)
+ FAIL(FATAL_ERROR_PARAMETER);
+ if(toInit == NULL || initializer == NULL)
+ return NULL;
+
+#if 1 // libtpms added begin
+ BnToBytes(initializer, buffer, &buffer_len); /* TPM to bin */
+ _toInit = BN_bin2bn(buffer, buffer_len, NULL); /* bin to ossl */
+ BN_set_flags(_toInit, BN_FLG_CONSTTIME);
+ BN_copy(toInit, _toInit);
+ BN_clear_free(_toInit);
+#else // libtpms added end
+ toInit->d = (BN_ULONG *)&initializer->d[0];
+ toInit->dmax = (int)initializer->allocated;
+ toInit->top = (int)initializer->size;
+ toInit->neg = 0;
+ toInit->flags = 0;
+#endif
+ return toInit;
+}
+
+#ifndef OSSL_DEBUG
+# define BIGNUM_PRINT(label, bn, eol)
+# define DEBUG_PRINT(x)
+#else
+# define DEBUG_PRINT(x) printf("%s", x)
+# define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol))
+
+static
+void BIGNUM_print(
+ const char *label,
+ const BIGNUM *a,
+ BOOL eol
+ )
+{
+ BN_ULONG *d;
+ int i;
+ int notZero = FALSE;
+ if(label != NULL)
+ printf("%s", label);
+ if(a == NULL)
+ {
+ printf("NULL");
+ goto done;
+ }
+ if (a->neg)
+ printf("-");
+ for(i = a->top, d = &a->d[i - 1]; i > 0; i--)
+ {
+ int j;
+ BN_ULONG l = *d--;
+ for(j = BN_BITS2 - 8; j >= 0; j -= 8)
+ {
+ BYTE b = (BYTE)((l >> j) & 0xFF);
+ notZero = notZero || (b != 0);
+ if(notZero)
+ printf("%02x", b);
+ }
+ if(!notZero)
+ printf("0");
+ }
+ done:
+ if(eol)
+ printf("\n");
+ return;
+}
+#endif
+
+/* B.2.3.2.3.4. BnNewVariable() */
+/* This function allocates a new variable in the provided context. If the context does not exist or
+ the allocation fails, it is a catastrophic failure. */
+static BIGNUM *
+BnNewVariable(
+ BN_CTX *CTX
+ )
+{
+ BIGNUM *new;
+ //
+ // This check is intended to protect against calling this function without
+ // having initialized the CTX.
+ if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL))
+ FAIL(FATAL_ERROR_ALLOCATION);
+ return new;
+}
+
+#if LIBRARY_COMPATIBILITY_CHECK
+
+BOOL
+MathLibraryCompatibilityCheck(
+ void
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *osslTemp = BnNewVariable(CTX);
+#if 0
+ crypt_uword_t i;
+#endif
+ BYTE test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
+ 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+ 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
+ BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value
+ //
+ // Convert the test data to a bigNum
+ BnFromBytes(tpmTemp, test, sizeof(test));
+ // Convert the test data to an OpenSSL BIGNUM
+ BN_bin2bn(test, sizeof(test), osslTemp);
+ // Make sure the values are consistent
+#if 0
+ VERIFY(osslTemp->top == (int)tpmTemp->size);
+ for(i = 0; i < tpmTemp->size; i++)
+ VERIFY(osslTemp->d[i] == tpmTemp->d[i]);
+#endif
+ OSSL_LEAVE();
+ return 1;
+#if 0
+ Error:
+ return 0;
+#endif
+}
+
+#endif
+
+/* B.2.3.2.3.3. BnModMult() */
+/* Does multiply and divide returning the remainder of the divide. */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnModMult(
+ bigNum result,
+ bigConst op1,
+ bigConst op2,
+ bigConst modulus
+ )
+{
+ OSSL_ENTER();
+ BOOL OK = TRUE;
+ BIGNUM *bnResult = BN_NEW();
+ BIGNUM *bnTemp = BN_NEW();
+ BIG_INITIALIZED(bnOp1, op1);
+ BIG_INITIALIZED(bnOp2, op2);
+ BIG_INITIALIZED(bnMod, modulus);
+ //
+ VERIFY(BN_mul(bnTemp, bnOp1, bnOp2, CTX));
+ VERIFY(BN_div(NULL, bnResult, bnTemp, bnMod, CTX));
+ VERIFY(OsslToTpmBn(result, bnResult));
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bnMod); // libtpms added
+ BN_clear_free(bnOp2); // libtpms added
+ BN_clear_free(bnOp1); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+
+/* B.2.3.2.3.4. BnMult() */
+/* Multiplies two numbers */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnMult(
+ bigNum result,
+ bigConst multiplicand,
+ bigConst multiplier
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *bnTemp = BN_NEW();
+ BOOL OK = TRUE;
+ BIG_INITIALIZED(bnA, multiplicand);
+ BIG_INITIALIZED(bnB, multiplier);
+ //
+ VERIFY(BN_mul(bnTemp, bnA, bnB, CTX));
+ VERIFY(OsslToTpmBn(result, bnTemp));
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bnB); // libtpms added
+ BN_clear_free(bnA); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+
+/* B.2.3.2.3.5. BnDiv() */
+/* This function divides two bigNum values. The function returns FALSE if there is an error in the
+ operation. */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnDiv(
+ bigNum quotient,
+ bigNum remainder,
+ bigConst dividend,
+ bigConst divisor
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *bnQ = BN_NEW();
+ BIGNUM *bnR = BN_NEW();
+ BOOL OK = TRUE;
+ BIG_INITIALIZED(bnDend, dividend);
+ BIG_INITIALIZED(bnSor, divisor);
+ //
+ if(BnEqualZero(divisor))
+ FAIL(FATAL_ERROR_DIVIDE_ZERO);
+ VERIFY(BN_div(bnQ, bnR, bnDend, bnSor, CTX));
+ VERIFY(OsslToTpmBn(quotient, bnQ));
+ VERIFY(OsslToTpmBn(remainder, bnR));
+ DEBUG_PRINT("In BnDiv:\n");
+ BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE);
+ BIGNUM_PRINT(" bnDivisor: ", bnSor, TRUE);
+ BIGNUM_PRINT(" bnQuotient: ", bnQ, TRUE);
+ BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE);
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bnSor); // libtpms added
+ BN_clear_free(bnDend); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+
+#if ALG_RSA
+#if !RSA_KEY_SIEVE // libtpms added
+/* B.2.3.2.3.6. BnGcd() */
+/* Get the greatest common divisor of two numbers */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnGcd(
+ bigNum gcd, // OUT: the common divisor
+ bigConst number1, // IN:
+ bigConst number2 // IN:
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *bnGcd = BN_NEW();
+ BOOL OK = TRUE;
+ BIG_INITIALIZED(bn1, number1);
+ BIG_INITIALIZED(bn2, number2);
+ //
+ BN_set_flags(bn1, BN_FLG_CONSTTIME); // number1 is secret prime number
+ VERIFY(BN_gcd(bnGcd, bn1, bn2, CTX));
+ VERIFY(OsslToTpmBn(gcd, bnGcd));
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bn2); // libtpms added
+ BN_clear_free(bn1); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+#endif // libtpms added
+
+/* B.2.3.2.3.7. BnModExp() */
+/* Do modular exponentiation using bigNum values. The conversion from a bignum_t to a bigNum is
+ trivial as they are based on the same structure */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnModExp(
+ bigNum result, // OUT: the result
+ bigConst number, // IN: number to exponentiate
+ bigConst exponent, // IN:
+ bigConst modulus // IN:
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *bnResult = BN_NEW();
+ BOOL OK = TRUE;
+ BIG_INITIALIZED(bnN, number);
+ BIG_INITIALIZED(bnE, exponent);
+ BIG_INITIALIZED(bnM, modulus);
+ //
+ BN_set_flags(bnE, BN_FLG_CONSTTIME); // exponent may be private
+ VERIFY(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX));
+ VERIFY(OsslToTpmBn(result, bnResult));
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bnM); // libtpms added
+ BN_clear_free(bnE); // libtpms added
+ BN_clear_free(bnN); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+
+/* B.2.3.2.3.8. BnModInverse() */
+/* Modular multiplicative inverse */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+
+LIB_EXPORT BOOL
+BnModInverse(
+ bigNum result,
+ bigConst number,
+ bigConst modulus
+ )
+{
+ OSSL_ENTER();
+ BIGNUM *bnResult = BN_NEW();
+ BOOL OK = TRUE;
+ BIG_INITIALIZED(bnN, number);
+ BIG_INITIALIZED(bnM, modulus);
+ //
+ BN_set_flags(bnN, BN_FLG_CONSTTIME); // number may be private
+ VERIFY(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL);
+ VERIFY(OsslToTpmBn(result, bnResult));
+ goto Exit;
+ Error:
+ OK = FALSE;
+ Exit:
+ BN_clear_free(bnM); // libtpms added
+ BN_clear_free(bnN); // libtpms added
+ OSSL_LEAVE();
+ return OK;
+}
+
+#endif // TPM_ALG_RSA
+
+#if ALG_ECC
+
+/* B.2.3.2.3.9. PointFromOssl() */
+/* Function to copy the point result from an OSSL function to a bigNum */
+/* Return Value Meaning */
+/* TRUE(1) success */
+/* FALSE(0) failure in operation */
+static BOOL
+PointFromOssl(
+ bigPoint pOut, // OUT: resulting point
+ EC_POINT *pIn, // IN: the point to return
+ bigCurve E // IN: the curve
+ )
+{
+ BIGNUM *x = NULL;
+ BIGNUM *y = NULL;
+ BOOL OK;
+ BN_CTX_start(E->CTX);
+ //
+ x = BN_CTX_get(E->CTX);
+ y = BN_CTX_get(E->CTX);
+ if(y == NULL)
+ FAIL(FATAL_ERROR_ALLOCATION);
+ // If this returns false, then the point is at infinity
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin
+ OK = EC_POINT_get_affine_coordinates(E->G, pIn, x, y, E->CTX);
+#else // libtpms added begin
+ OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX);
+#endif // libtpms added end
+ if(OK)
+ {
+ OsslToTpmBn(pOut->x, x);
+ OsslToTpmBn(pOut->y, y);
+ BnSetWord(pOut->z, 1);
+ }
+ else
+ BnSetWord(pOut->z, 0);
+ BN_CTX_end(E->CTX);
+ return OK;
+}
+/* B.2.3.2.3.10. EcPointInitialized() */
+/* Allocate and initialize a point. */
+
+LIB_EXPORT EC_POINT * // libtpms: exported function
+EcPointInitialized(
+ pointConst initializer,
+ bigCurve E
+ )
+{
+ EC_POINT *P = NULL;
+
+ if(initializer != NULL)
+ {
+ BIG_INITIALIZED(bnX, initializer->x);
+ BIG_INITIALIZED(bnY, initializer->y);
+ if(E == NULL)
+ FAIL(FATAL_ERROR_ALLOCATION);
+ P = EC_POINT_new(E->G);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin
+ if(!EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, E->CTX))
+#else // libtpms added end
+ if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX))
+#endif // libtpms added
+ P = NULL;
+ BN_clear_free(bnX); // libtpms added
+ BN_clear_free(bnY); // libtpms added
+ }
+ return P;
+}
+
+/* B.2.3.2.3.11. BnCurveInitialize() */
+/* This function initializes the OpenSSL group definition */
+/* It is a fatal error if groupContext is not provided. */
+/* Return Values Meaning */
+/* NULL the TPM_ECC_CURVE is not valid */
+/* non-NULL points to a structure in groupContext */
+
+LIB_EXPORT bigCurve
+BnCurveInitialize(
+ bigCurve E, // IN: curve structure to initialize
+ TPM_ECC_CURVE curveId // IN: curve identifier
+ )
+{
+ const ECC_CURVE_DATA *C = GetCurveData(curveId);
+ if(C == NULL)
+ E = NULL;
+ if(E != NULL)
+ {
+ // This creates the OpenSSL memory context that stays in effect as long as the
+ // curve (E) is defined.
+ OSSL_ENTER(); // if the allocation fails, the TPM fails
+ EC_POINT *P = NULL;
+ BIG_INITIALIZED(bnP, C->prime);
+ BIG_INITIALIZED(bnA, C->a);
+ BIG_INITIALIZED(bnB, C->b);
+ BIG_INITIALIZED(bnX, C->base.x);
+ BIG_INITIALIZED(bnY, C->base.y);
+ BIG_INITIALIZED(bnN, C->order);
+ BIG_INITIALIZED(bnH, C->h);
+ //
+ E->C = C;
+ E->CTX = CTX;
+
+ // initialize EC group, associate a generator point and initialize the point
+ // from the parameter data
+ // Create a group structure
+ E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX);
+ VERIFY(E->G != NULL);
+
+ // Allocate a point in the group that will be used in setting the
+ // generator. This is not needed after the generator is set.
+ P = EC_POINT_new(E->G);
+ VERIFY(P != NULL);
+
+ // Need to use this in case Montgomery method is being used
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin
+ VERIFY(EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, CTX));
+#else // libtpms added end
+ VERIFY(EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX));
+#endif // libtpms added
+ // Now set the generator
+ VERIFY(EC_GROUP_set_generator(E->G, P, bnN, bnH));
+
+ EC_POINT_free(P);
+ goto Exit_free; // libtpms changed
+ Error:
+ EC_POINT_free(P);
+ BnCurveFree(E);
+ E = NULL;
+
+ Exit_free: // libtpms added begin
+ BN_clear_free(bnH);
+ BN_clear_free(bnN);
+ BN_clear_free(bnY);
+ BN_clear_free(bnX);
+ BN_clear_free(bnB);
+ BN_clear_free(bnA);
+ BN_clear_free(bnP); // libtpms added end
+ }
+// Exit:
+ return E;
+}
+
+/* B.2.3.2.3.15. BnCurveFree() */
+/* This function will free the allocated components of the curve and end the frame in which the
+ curve data exists */
+LIB_EXPORT void
+BnCurveFree(
+ bigCurve E
+ )
+{
+ if(E)
+ {
+ EC_GROUP_free(E->G);
+ OsslContextLeave(E->CTX);
+ }
+}
+
+/* B.2.3.2.3.11. BnEccModMult() */
+/* This functi2n does a point multiply of the form R = [d]S */
+/* Return Values Meaning */
+/* FALSE failure in operation; treat as result being point at infinity */
+
+LIB_EXPORT BOOL
+BnEccModMult(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: point to multiply by 'd' (optional)
+ bigConst d, // IN: scalar for [d]S
+ bigCurve E
+ )
+{
+ EC_POINT *pR = EC_POINT_new(E->G);
+ EC_POINT *pS = EcPointInitialized(S, E);
+ BIG_INITIALIZED(bnD, d);
+
+ if(S == NULL)
+ EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX);
+ else
+ EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX);
+ PointFromOssl(R, pR, E);
+ EC_POINT_clear_free(pR); // libtpms changed
+ EC_POINT_clear_free(pS); // libtpms changed
+ BN_clear_free(bnD); // libtpms added
+ return !BnEqualZero(R->z);
+}
+
+/* B.2.3.2.3.13. BnEccModMult2() */
+/* This function does a point multiply of the form R = [d]G + [u]Q */
+/* FALSE failure in operation; treat as result being point at infinity */
+
+LIB_EXPORT BOOL
+BnEccModMult2(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: optional point
+ bigConst d, // IN: scalar for [d]S or [d]G
+ pointConst Q, // IN: second point
+ bigConst u, // IN: second scalar
+ bigCurve E // IN: curve
+ )
+{
+ EC_POINT *pR = EC_POINT_new(E->G);
+ EC_POINT *pS = EcPointInitialized(S, E);
+ BIG_INITIALIZED(bnD, d);
+ EC_POINT *pQ = EcPointInitialized(Q, E);
+ BIG_INITIALIZED(bnU, u);
+
+ if(S == NULL || S == (pointConst)&(AccessCurveData(E)->base))
+ EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX);
+ else
+ {
+ const EC_POINT *points[2];
+ const BIGNUM *scalars[2];
+ points[0] = pS;
+ points[1] = pQ;
+ scalars[0] = bnD;
+ scalars[1] = bnU;
+ EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX);
+ }
+ PointFromOssl(R, pR, E);
+ EC_POINT_clear_free(pR); // libtpms changed
+ EC_POINT_clear_free(pS); // libtpms changed
+ EC_POINT_clear_free(pQ); // libtpms changed
+ BN_clear_free(bnD); // libtpms added
+ BN_clear_free(bnU); // libtpms added
+
+ return !BnEqualZero(R->z);
+}
+
+/* B.2.3.2.4. BnEccAdd() */
+/* This function does addition of two points. */
+/* Return Values Meaning */
+/* FALSE failure in operation; treat as result being point at infinity */
+LIB_EXPORT BOOL
+BnEccAdd(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: point to multiply by 'd'
+ pointConst Q, // IN: second point
+ bigCurve E // IN: curve
+ )
+{
+ EC_POINT *pR = EC_POINT_new(E->G);
+ EC_POINT *pS = EcPointInitialized(S, E);
+ EC_POINT *pQ = EcPointInitialized(Q, E);
+ //
+ EC_POINT_add(E->G, pR, pS, pQ, E->CTX);
+ PointFromOssl(R, pR, E);
+ EC_POINT_clear_free(pR); // libtpms changed
+ EC_POINT_clear_free(pS); // libtpms changed
+ EC_POINT_clear_free(pQ); // libtpms changed
+ return !BnEqualZero(R->z);
+}
+
+#endif // ALG_ECC
+#endif // MATH_LIB_OSSL
diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath.h b/src/tpm2/crypto/openssl/TpmToOsslMath.h
new file mode 100644
index 0000000..47333c7
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslMath.h
@@ -0,0 +1,164 @@
+/********************************************************************************/
+/* */
+/* TPM to OpenSSL BigNum Shim Layer */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslMath.h 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* B.2.2.1. TpmToOsslMath.h */
+/* B.2.2.1.1. Introduction */
+/* This file contains the structure definitions used for ECC in the OpenSSL version of the
+ code. These definitions would change, based on the library. The ECC-related structures that cross
+ the TPM interface are defined in TpmTypes.h */
+
+#ifndef MATH_LIB_DEFINED
+#define MATH_LIB_DEFINED
+#define MATH_LIB_OSSL
+#include <openssl/evp.h>
+#include <openssl/ec.h>
+
+#define SYMMETRIC_ALIGNMENT RADIX_BYTES
+
+#if 0 // libtpms added
+#if OPENSSL_VERSION_NUMBER >= 0x10200000L
+// Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the
+// version check or provide the new definition for this version.
+# error Untested OpenSSL version
+#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
+// from crypto/bn/bn_lcl.h
+struct bignum_st {
+ BN_ULONG *d;
+ int top;
+
+ int dmax;
+ int neg;
+ int flags;
+};
+#if 0 // libtpms added
+# define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp
+# define EC_POINT_set_affine_coordinates EC_POINT_set_affine_coordinates_GFp
+#endif // libtpms added
+#endif // OPENSSL_VERSION_NUMBER
+#endif // libtpms added
+
+#include <openssl/bn.h>
+#if USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added begin
+#include <openssl/ecdsa.h>
+#endif // libtpms added end
+
+/* B.2.2.2.2. Macros and Defines */
+/* Make sure that the library is using the correct size for a crypt word */
+
+#if defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \
+ || ((defined SIXTY_FOUR_BIT_LONG || defined SIXTY_FOUR_BIT) \
+ && (RADIX_BITS != 64))
+# error Ossl library is using different radix
+#endif
+
+/* Allocate a local BIGNUM value. For the allocation, a bigNum structure is created as is a local
+ BIGNUM. The bigNum is initialized and then the BIGNUM is set to reference the local value. */
+
+#define BIG_VAR(name, bits) \
+ BN_VAR(name##Bn, (bits)); \
+ BIGNUM *_##name = BN_new(); /* libtpms */ \
+ BIGNUM *name = BigInitialized(_##name, /* libtpms */ \
+ BnInit(name##Bn, \
+ BYTES_TO_CRYPT_WORDS(sizeof(_##name##Bn.d))))
+
+/* Allocate a BIGNUM and initialize with the values in a bigNum initializer */
+
+#define BIG_INITIALIZED(name, initializer) \
+ BIGNUM *_##name = BN_new(); /* libtpms */ \
+ BIGNUM *name = BigInitialized(_##name, initializer) /* libtpms */
+
+typedef struct
+{
+ const ECC_CURVE_DATA *C; // the TPM curve values
+ EC_GROUP *G; // group parameters
+ BN_CTX *CTX; // the context for the math (this might not be
+ // the context in which the curve was created>;
+} OSSL_CURVE_DATA;
+typedef OSSL_CURVE_DATA *bigCurve;
+#define AccessCurveData(E) ((E)->C)
+
+#include "TpmToOsslSupport_fp.h"
+
+#define OSSL_ENTER() BN_CTX *CTX = OsslContextEnter()
+#define OSSL_LEAVE() OsslContextLeave(CTX)
+
+/* Start and end a context that spans multiple ECC functions. This is used so that the group for the
+ curve can persist across multiple frames. */
+
+#define CURVE_INITIALIZED(name, initializer) \
+ OSSL_CURVE_DATA _##name; \
+ bigCurve name = BnCurveInitialize(&_##name, initializer)
+
+#define CURVE_FREE(name) BnCurveFree(name)
+
+/* Start and end a local stack frame within the context of the curve frame */
+#if 0 /* kgold not used */
+#define ECC_ENTER() BN_CTX *CTX = OsslPushContext(E->CTX)
+#define ECC_LEAVE() OsslPopContext(CTX)
+#endif
+#define BN_NEW() BnNewVariable(CTX)
+
+
+/* This definition would change if there were something to report */
+#define MathLibSimulationEnd()
+#endif // MATH_LIB_DEFINED
+
+
diff --git a/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h b/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h
new file mode 100644
index 0000000..7c42e71
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h
@@ -0,0 +1,152 @@
+/********************************************************************************/
+/* */
+/* TPM to OpenSSL BigNum Shim Layer */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslMath_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef TPMTOOSSLMATH_FP_H
+#define TPMTOOSSLMATH_FP_H
+
+#include <openssl/bn.h>
+
+BOOL
+OsslToTpmBn(
+ bigNum bn,
+ const BIGNUM *osslBn // libtpms added 'const'
+ );
+BIGNUM *
+BigInitialized(
+ BIGNUM *toInit,
+ bigConst initializer
+ );
+// libtpms added begin
+EC_POINT *
+EcPointInitialized(
+ pointConst initializer,
+ bigCurve E
+ );
+// libtpms added end
+LIB_EXPORT BOOL
+BnModMult(
+ bigNum result,
+ bigConst op1,
+ bigConst op2,
+ bigConst modulus
+ );
+LIB_EXPORT BOOL
+BnMult(
+ bigNum result,
+ bigConst multiplicand,
+ bigConst multiplier
+ );
+LIB_EXPORT BOOL
+BnDiv(
+ bigNum quotient,
+ bigNum remainder,
+ bigConst dividend,
+ bigConst divisor
+ );
+LIB_EXPORT BOOL
+BnGcd(
+ bigNum gcd, // OUT: the common divisor
+ bigConst number1, // IN:
+ bigConst number2 // IN:
+ );
+LIB_EXPORT BOOL
+BnModExp(
+ bigNum result, // OUT: the result
+ bigConst number, // IN: number to exponentiate
+ bigConst exponent, // IN:
+ bigConst modulus // IN:
+ );
+LIB_EXPORT BOOL
+BnModInverse(
+ bigNum result,
+ bigConst number,
+ bigConst modulus
+ );
+bigCurve
+BnCurveInitialize(
+ bigCurve E, // IN: curve structure to initialize
+ TPM_ECC_CURVE curveId // IN: curve identifier
+ );
+LIB_EXPORT BOOL
+BnEccModMult(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: point to multiply by 'd' (optional)
+ bigConst d, // IN: scalar for [d]S
+ bigCurve E
+ );
+LIB_EXPORT BOOL
+BnEccModMult2(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: optional point
+ bigConst d, // IN: scalar for [d]S or [d]G
+ pointConst Q, // IN: second point
+ bigConst u, // IN: second scalar
+ bigCurve E // IN: curve
+ );
+LIB_EXPORT BOOL
+BnEccAdd(
+ bigPoint R, // OUT: computed point
+ pointConst S, // IN: point to multiply by 'd'
+ pointConst Q, // IN: second point
+ bigCurve E // IN: curve
+ );
+
+#endif
diff --git a/src/tpm2/crypto/openssl/TpmToOsslSupport.c b/src/tpm2/crypto/openssl/TpmToOsslSupport.c
new file mode 100644
index 0000000..921b02f
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslSupport.c
@@ -0,0 +1,129 @@
+/********************************************************************************/
+/* */
+/* Initialization of the Interface to the OpenSSL Library. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslSupport.c 1519 2019-11-15 20:43:51Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+/* B.2.3.3. TpmToOsslSupport.c */
+/* B.2.3.3.1. Introduction */
+/* The functions in this file are used for initialization of the interface to the OpenSSL
+ library. */
+/* B.2.3.3.2. Defines and Includes */
+#include "Tpm.h"
+
+#if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL)
+
+/* Used to pass the pointers to the correct sub-keys */
+typedef const BYTE *desKeyPointers[3];
+/* B.2.3.3.2.1. SupportLibInit() */
+/* This does any initialization required by the support library. */
+LIB_EXPORT int
+SupportLibInit(
+ void
+ )
+{
+ return TRUE;
+}
+/* B.2.3.3.2.2. OsslContextEnter() */
+/* This function is used to initialize an OpenSSL context at the start of a function that will
+ call to an OpenSSL math function. */
+BN_CTX *
+OsslContextEnter(
+ void
+ )
+{
+ BN_CTX *CTX = BN_CTX_new();
+ return OsslPushContext(CTX);
+}
+/* B.2.3.3.2.3. OsslContextLeave() */
+/* This is the companion function to OsslContextEnter(). */
+void
+OsslContextLeave(
+ BN_CTX *CTX
+ )
+{
+ OsslPopContext(CTX);
+ BN_CTX_free(CTX);
+}
+
+/* B.2.3.3.2.4. OsslPushContext() */
+/* This function is used to create a frame in a context. All values allocated within this context after the frame is started will be automatically freed when the context (OsslPopContext() */
+BN_CTX *
+OsslPushContext(
+ BN_CTX *CTX
+ )
+{
+ if(CTX == NULL)
+ FAIL(FATAL_ERROR_ALLOCATION);
+ BN_CTX_start(CTX);
+ return CTX;
+}
+
+/* B.2.3.3.2.5. OsslPopContext() */
+/* This is the companion function to OsslPushContext(). */
+void
+OsslPopContext(
+ BN_CTX *CTX
+ )
+{
+ // BN_CTX_end can't be called with NULL. It will blow up.
+ if(CTX != NULL)
+ BN_CTX_end(CTX);
+}
+
+#endif // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSL
diff --git a/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h b/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h
new file mode 100644
index 0000000..c8d7b5a
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h
@@ -0,0 +1,83 @@
+/********************************************************************************/
+/* */
+/* Initialization of the Interface to the OpenSSL Library */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslSupport_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2019 */
+/* */
+/********************************************************************************/
+
+#ifndef TPMTOOSSLSUPPORT_FP_H
+#define TPMTOOSSLSUPPORT_FP_H
+
+BN_CTX *
+OsslContextEnter(
+ void
+ );
+void
+OsslContextLeave(
+ BN_CTX *context
+ );
+BN_CTX *
+OsslPushContext(
+ BN_CTX *CTX
+ );
+void
+OsslPopContext(
+ BN_CTX *CTX
+ );
+
+
+#endif
diff --git a/src/tpm2/crypto/openssl/TpmToOsslSym.h b/src/tpm2/crypto/openssl/TpmToOsslSym.h
new file mode 100644
index 0000000..521204f
--- /dev/null
+++ b/src/tpm2/crypto/openssl/TpmToOsslSym.h
@@ -0,0 +1,197 @@
+/********************************************************************************/
+/* */
+/* Splice the OpenSSL() library into the TPM code. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: TpmToOsslSym.h 1619 2020-05-19 16:51:47Z kgoldman $ */
+/* */
+/* 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 (admin@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, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+/* B.2.3.2. TpmToOsslSym.h */
+/* B.2.3.2.1. Introduction */
+/* This header file is used to splice the OpenSSL() library into the TPM code. */
+/* The support required of a library are a hash module, a block cipher module and portions of a big
+ number library. All of the library-dependent headers should have the same guard to that only the
+ first one gets defined. */
+
+#ifndef SYM_LIB_DEFINED
+#define SYM_LIB_DEFINED
+#define SYM_LIB_OSSL
+#include <openssl/aes.h>
+#if ALG_TDES
+#include <openssl/des.h>
+#endif
+
+#if ALG_SM4
+# if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L
+# undef ALG_SM4
+# define ALG_SM4 ALG_NO
+# elif OPENSSL_VERSION_NUMBER >= 0x10200000L
+# include <openssl/sm4.h>
+# else
+// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory,
+// and they do not get installed as part of the libssl package
+
+# define SM4_KEY_SCHEDULE 32
+
+typedef struct SM4_KEY_st {
+ uint32_t rk[SM4_KEY_SCHEDULE];
+} SM4_KEY;
+
+int SM4_set_key(const uint8_t *key, SM4_KEY *ks);
+void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
+void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
+# endif // OpenSSL < 1.2
+#endif // ALG_SM4
+
+#if ALG_CAMELLIA
+#include <openssl/camellia.h>
+#endif
+#include <openssl/bn.h>
+#include <openssl/ossl_typ.h>
+
+/* B.2.2.3.2. Links to the OpenSSL symmetric algorithms */
+// The Crypt functions that call the block encryption function use the parameters in the order:
+// a) keySchedule
+// b) in buffer
+// c) out buffer Since open SSL uses the order in encryptoCall_t above, need to swizzle the values
+// to the order required by the library.
+
+#define SWIZZLE(keySchedule, in, out) \
+ (const BYTE *)(in), (BYTE *)(out), (void *)(keySchedule)
+
+// Define the order of parameters to the library functions that do block encryption and decryption.
+
+typedef void(*TpmCryptSetSymKeyCall_t)(
+ const BYTE *in,
+ BYTE *out,
+ void *keySchedule
+ );
+
+#define SYM_ALIGNMENT 4 /* libtpms: keep old value */
+
+/* B.2.2.3.3. Links to the OpenSSL AES code */
+/* Macros to set up the encryption/decryption key schedules */
+
+#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \
+ AES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule))
+#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \
+ AES_set_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule))
+
+/* Macros to alias encryption calls to specific algorithms. This should be used
+ sparingly. Currently, only used by CryptSym.c and CryptRand.c */
+/* When using these calls, to call the AES block encryption code, the caller should use:
+ TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); */
+
+#define TpmCryptEncryptAES AES_encrypt
+#define TpmCryptDecryptAES AES_decrypt
+#define tpmKeyScheduleAES AES_KEY
+
+/* B.2.2.3.4. Links to the OpenSSL DES code */
+
+#if ALG_TDES && 0 // libtpms changed
+#include "TpmToOsslDesSupport_fp.h"
+#endif
+
+#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \
+ TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule))
+#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \
+ TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule))
+
+/* Macros to alias encryption calls to specific algorithms. This should be used
+ sparingly. Currently, only used by CryptRand.c */
+
+#define TpmCryptEncryptTDES TDES_encrypt
+#define TpmCryptDecryptTDES TDES_decrypt
+#define tpmKeyScheduleTDES DES_key_schedule
+
+#if ALG_TDES // libtpms added begin
+#include "TpmToOsslDesSupport_fp.h"
+#endif // libtpms added end
+
+/* B.2.2.3.5. Links to the OpenSSL SM4 code */
+/* Macros to set up the encryption/decryption key schedules */
+
+#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \
+ SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule))
+#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \
+ SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule))
+/* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */
+
+#define TpmCryptEncryptSM4 SM4_encrypt
+#define TpmCryptDecryptSM4 SM4_decrypt
+#define tpmKeyScheduleSM4 SM4_KEY
+
+/* B.2.2.3.6. Links to the OpenSSL CAMELLIA code */
+/* Macros to set up the encryption/decryption key schedules */
+
+#define TpmCryptSetEncryptKeyCAMELLIA(key, keySizeInBits, schedule) \
+ Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule))
+#define TpmCryptSetDecryptKeyCAMELLIA(key, keySizeInBits, schedule) \
+ Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule))
+
+/* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */
+
+#define TpmCryptEncryptCAMELLIA Camellia_encrypt
+#define TpmCryptDecryptCAMELLIA Camellia_decrypt
+#define tpmKeyScheduleCAMELLIA CAMELLIA_KEY
+
+/* Forward reference */
+
+// kgold typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t;
+
+/* This definition would change if there were something to report */
+#define SymLibSimulationEnd()
+#endif // SYM_LIB_DEFINED
diff --git a/src/tpm2/crypto/openssl/consttime.txt b/src/tpm2/crypto/openssl/consttime.txt
new file mode 100644
index 0000000..6dd8328
--- /dev/null
+++ b/src/tpm2/crypto/openssl/consttime.txt
@@ -0,0 +1,76 @@
+The following (top level) 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
+ - BN_copy: YES, DONE
+ BnModMult:
+ - BN_mul: no
+ - BN_div: -> BN_copy: ?
+ BnMult:
+ - BN_mul: no
+ BnDiv:
+ - BN_div: -> BN_copy: ?
+ BnGcd: /* FUNCTION IS NOT USED */
+ - 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)
diff --git a/src/tpm2/crypto/openssl/consttime.txt' b/src/tpm2/crypto/openssl/consttime.txt'
new file mode 100644
index 0000000..b667086
--- /dev/null
+++ b/src/tpm2/crypto/openssl/consttime.txt'
@@ -0,0 +1,58 @@
+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
+ - BN_dup:
+ - BN_sub:
+ - BN_add_word:
+ - BN_mod_inverse: yes
+ - BN_set_word:
+ - BN_bin2bn:
+ - BN_div:
+ - BN_is_zero:
+
+TpmToOsslMath:
+ OsslToTpmBn:
+ - BN_num_bytes:
+ - BN_bn2bin:
+ BigInitialized:
+ - BN_bin2bn:
+ - BN_copy:
+ BnModMult:
+ - BN_mul:
+ - BN_div:
+ BnMult:
+ - BN_mul:
+ BnDiv:
+ - BN_div:
+ BnGcd:
+ - BN_gcd:
+ BnModExp:
+ - BN_mod_exp: YES
+ BnModInverse:
+ - BN_mod_inverse: YES