rev180: Sync ECC and dependencies with upstream

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2023-12-17 21:39:15 -05:00 committed by Stefan Berger
parent 67820395b9
commit 3e0cf3eb45
42 changed files with 2868 additions and 1795 deletions

View File

@ -197,6 +197,7 @@ libtpms_tpm2_la_SOURCES = \
tpm2/Attest_spt.c \
tpm2/AuditCommands.c \
tpm2/Bits.c \
tpm2/BnEccConstants.c \
tpm2/BnConvert.c \
tpm2/BnMath.c \
tpm2/BnMemory.c \
@ -275,6 +276,8 @@ libtpms_tpm2_la_SOURCES = \
tpm2/TpmEcc_Signature_Schnorr.c \
tpm2/TpmEcc_Signature_SM2.c \
tpm2/TpmEcc_Signature_Util.c \
tpm2/TpmEcc_Util.c \
tpm2/TpmMath_Debug.c \
tpm2/TpmMath_Util.c \
tpm2/TpmSizeChecks.c \
tpm2/TPMCmdp.c \
@ -329,6 +332,7 @@ noinst_HEADERS += \
tpm2/Attest_spt_fp.h \
tpm2/BaseTypes.h \
tpm2/Bits_fp.h \
tpm2/BnEccConstants.c \
tpm2/BnSupport_Interface.h \
tpm2/BnUtil_fp.h \
tpm2/Capabilities.h \
@ -363,6 +367,7 @@ noinst_HEADERS += \
tpm2/DictionaryAttackLockReset_fp.h \
tpm2/DictionaryAttackParameters_fp.h \
tpm2/Duplicate_fp.h \
tpm2/EccConstantData.inl \
tpm2/EccTestData.h \
tpm2/ECC_Parameters_fp.h \
tpm2/ECDH_KeyGen_fp.h \
@ -521,6 +526,7 @@ noinst_HEADERS += \
tpm2/TpmEcc_Signature_SM2_fp.h \
tpm2/TpmEcc_Signature_Util_fp.h \
tpm2/TpmFail_fp.h \
tpm2/TpmMath_Debug_fp.h \
tpm2/TpmMath_Util_fp.h \
tpm2/TpmProfile.h \
tpm2/TpmProfile_CommandList.h \
@ -536,6 +542,7 @@ noinst_HEADERS += \
tpm2/_TPM_Hash_Start_fp.h \
tpm2/_TPM_Init_fp.h \
tpm2/TpmCalculatedAttributes.h \
tpm2/TpmEcc_Util_fp.h \
tpm2/TpmSizeChecks_fp.h \
tpm2/TpmTcpProtocol.h \
tpm2/TpmTypes.h \
@ -582,6 +589,7 @@ libtpms_tpm2_la_SOURCES += \
tpm2/crypto/openssl/TpmToOsslSupport.c
noinst_HEADERS += \
tpm2/crypto/openssl/BnToOsslMath_fp.h \
tpm2/crypto/openssl/BnToOsslMath.h \
tpm2/crypto/openssl/ConsttimeUtils.h \
tpm2/crypto/openssl/BnConvert_fp.h \
@ -594,7 +602,6 @@ noinst_HEADERS += \
tpm2/crypto/openssl/TpmToTpmBigNumMath.h \
tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h \
tpm2/crypto/openssl/TpmToOsslHash.h \
tpm2/crypto/openssl/TpmToOsslMath_fp.h \
tpm2/crypto/openssl/TpmToOsslSupport_fp.h \
tpm2/crypto/openssl/TpmToOsslSym.h \
tpm2/crypto/openssl/tpm_radix.h

View File

@ -129,51 +129,6 @@ LIB_EXPORT bigNum BnFrom2B(bigNum bn, // OUT:
BnSetTop(bn, 0); // Function accepts NULL
return NULL;
}
/* 10.2.2.3.3 BnFromHex() */
/* Convert a hex string into a bigNum. This is primarily used in debugging. */
#ifdef _SM2_SIGN_DEBUG // libtpms added
LIB_EXPORT bigNum
BnFromHex(
bigNum bn, // OUT:
const char *hex // IN:
)
{
#define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) \
: ((a) > 'A') ? ('A' - 10) : '0'))
unsigned i;
unsigned wordCount;
const char *p;
BYTE *d = (BYTE *)&(bn->d[0]);
//
pAssert(bn && hex);
i = (unsigned)strlen(hex);
wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2);
if((i == 0) || (wordCount >= BnGetAllocated(bn)))
BnSetWord(bn, 0);
else
{
bn->d[wordCount - 1] = 0;
p = hex + i - 1;
for(;i > 1; i -= 2)
{
BYTE a;
a = FromHex(*p);
p--;
*d++ = a + (FromHex(*p) << 4);
p--;
}
if(i == 1)
*d = FromHex(*p);
}
#if !BIG_ENDIAN_TPM
for(i = 0; i < wordCount; i++)
bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]);
#endif // BIG_ENDIAN_TPM
BnSetTop(bn, wordCount);
return bn;
}
#endif // libtpms added
//*** BnToBytes()
// This function converts a BIG_NUM to a byte array. It converts the bigNum to a
@ -263,49 +218,48 @@ LIB_EXPORT BOOL BnTo2B(bigConst bn, // IN:
#if ALG_ECC
/* 10.2.2.3.6 BnPointFrom2B() */
/* Function to create a BIG_POINT structure from a 2B point. A point is going to be two ECC values
in the same buffer. The values are going to be the size of the modulus. They are in modular
form. */
LIB_EXPORT bn_point_t *
BnPointFrom2B(
bigPoint ecP, // OUT: the preallocated point structure
TPMS_ECC_POINT *p // IN: the number to convert
)
//*** BnPointFromBytes()
// Function to create a BIG_POINT structure from a byte buffer in big-endian order.
// A point is going to be two ECC values in the same buffer. The values are going
// to be the size of the modulus. They are in modular form.
LIB_EXPORT bn_point_t* BnPointFromBytes(
bigPoint ecP, // OUT: the preallocated point structure
const BYTE* x,
NUMBYTES nBytesX,
const BYTE* y,
NUMBYTES nBytesY)
{
if(p == NULL)
if(x == NULL || y == NULL)
return NULL;
if(NULL != ecP)
{
BnFrom2B(ecP->x, &p->x.b);
BnFrom2B(ecP->y, &p->y.b);
BnFromBytes(ecP->x, x, nBytesX);
BnFromBytes(ecP->y, y, nBytesY);
BnSetWord(ecP->z, 1);
}
return ecP;
}
/* 10.2.2.3.7 BnPointTo2B() */
/* This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT contains two
TPM2B_ECC_PARAMETER values. The maximum size of the parameters is dependent on the maximum EC key
size used in an implementation. The presumption is that the TPMS_ECC_POINT is large enough to
hold 2 TPM2B values, each as large as a MAX_ECC_PARAMETER_BYTES */
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
)
//*** BnPointToBytes()
// This function extracts coordinates from a BIG_POINT into
// most-significant-byte-first memory buffers (the native format of
// a TPMS_ECC_POINT.)
// on input the NUMBYTES* parameters indicate the maximum buffer size.
// on output, they represent the amount of significant data in that buffer.
LIB_EXPORT BOOL BnPointToBytes(
pointConst ecP, // OUT: the preallocated point structure
BYTE* x,
NUMBYTES* pBytesX,
BYTE* y,
NUMBYTES* pBytesY)
{
UINT16 size;
//
pAssert(p && ecP && E);
pAssert(ecP && x && y && pBytesX && pBytesY);
pAssert(BnEqualWord(ecP->z, 1));
// BnMsb is the bit number of the MSB. This is one less than the number of bits
size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E))));
BnTo2B(ecP->x, &p->x.b, size);
BnTo2B(ecP->y, &p->y.b, size);
return TRUE;
BOOL result = BnToBytes(ecP->x, x, pBytesX);
result = result && BnToBytes(ecP->y, y, pBytesY);
// TODO: zeroize on error?
return result;
}
#endif // ALG_ECC

250
src/tpm2/BnEccConstants.c Normal file
View File

@ -0,0 +1,250 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
/*(Auto-generated)
* Created by TpmStructures; Version 4.4 Mar 26, 2019
* Date: Aug 30, 2019 Time: 02:11:52PM
*/
#include "TpmBigNum.h"
//#include "Tpm.h"
// TODO_RENAME_INC_FOLDER:private refers to the TPM_CoreLib private headers
#include "OIDs.h"
#if ALG_ECC
// define macros expected by EccConstantData to convert the data to BigNum format
# define TO_ECC_64 TO_CRYPT_WORD_64
# define TO_ECC_56(a, b, c, d, e, f, g) TO_ECC_64(0, a, b, c, d, e, f, g)
# define TO_ECC_48(a, b, c, d, e, f) TO_ECC_64(0, 0, a, b, c, d, e, f)
# define TO_ECC_40(a, b, c, d, e) TO_ECC_64(0, 0, 0, a, b, c, d, e)
# if RADIX_BITS > 32
# define TO_ECC_32(a, b, c, d) TO_ECC_64(0, 0, 0, 0, a, b, c, d)
# define TO_ECC_24(a, b, c) TO_ECC_64(0, 0, 0, 0, 0, a, b, c)
# define TO_ECC_16(a, b) TO_ECC_64(0, 0, 0, 0, 0, 0, a, b)
# define TO_ECC_8(a) TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a)
# else // RADIX_BITS == 32
# define TO_ECC_32 BIG_ENDIAN_BYTES_TO_UINT32
# define TO_ECC_24(a, b, c) TO_ECC_32(0, a, b, c)
# define TO_ECC_16(a, b) TO_ECC_32(0, 0, a, b)
# define TO_ECC_8(a) TO_ECC_32(0, 0, 0, a)
# endif
# define TO_ECC_192(a, b, c) c, b, a
# define TO_ECC_224(a, b, c, d) d, c, b, a
# define TO_ECC_256(a, b, c, d) d, c, b, a
# define TO_ECC_384(a, b, c, d, e, f) f, e, d, c, b, a
# define TO_ECC_528(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a
# define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a
# define BN_MIN_ALLOC(bytes) \
(BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes)
# define ECC_CONST(NAME, bytes, initializer) \
const struct \
{ \
crypt_uword_t allocate, size, d[BN_MIN_ALLOC(bytes)]; \
} NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes), {initializer}}
// This file contains the raw data for ECC curve constants. The data is wrapped
// in macros so this file can be included in other files that format the data in
// a memory format desired by the user. This file itself is never used alone.
# include "EccConstantData.inl"
// now define the TPMBN_ECC_CURVE_CONSTANTS objects for the known curves
# if ECC_NIST_P192
const TPMBN_ECC_CURVE_CONSTANTS NIST_P192 = {TPM_ECC_NIST_P192,
(bigNum)&NIST_P192_p,
(bigNum)&NIST_P192_n,
(bigNum)&NIST_P192_h,
(bigNum)&NIST_P192_a,
(bigNum)&NIST_P192_b,
{(bigNum)&NIST_P192_gX,
(bigNum)&NIST_P192_gY,
(bigNum)&NIST_P192_gZ}};
# endif // ECC_NIST_P192
# if ECC_NIST_P224
const TPMBN_ECC_CURVE_CONSTANTS NIST_P224 = {TPM_ECC_NIST_P224,
(bigNum)&NIST_P224_p,
(bigNum)&NIST_P224_n,
(bigNum)&NIST_P224_h,
(bigNum)&NIST_P224_a,
(bigNum)&NIST_P224_b,
{(bigNum)&NIST_P224_gX,
(bigNum)&NIST_P224_gY,
(bigNum)&NIST_P224_gZ}};
# endif // ECC_NIST_P224
# if ECC_NIST_P256
const TPMBN_ECC_CURVE_CONSTANTS NIST_P256 = {TPM_ECC_NIST_P256,
(bigNum)&NIST_P256_p,
(bigNum)&NIST_P256_n,
(bigNum)&NIST_P256_h,
(bigNum)&NIST_P256_a,
(bigNum)&NIST_P256_b,
{(bigNum)&NIST_P256_gX,
(bigNum)&NIST_P256_gY,
(bigNum)&NIST_P256_gZ}};
# endif // ECC_NIST_P256
# if ECC_NIST_P384
const TPMBN_ECC_CURVE_CONSTANTS NIST_P384 = {TPM_ECC_NIST_P384,
(bigNum)&NIST_P384_p,
(bigNum)&NIST_P384_n,
(bigNum)&NIST_P384_h,
(bigNum)&NIST_P384_a,
(bigNum)&NIST_P384_b,
{(bigNum)&NIST_P384_gX,
(bigNum)&NIST_P384_gY,
(bigNum)&NIST_P384_gZ}};
# endif // ECC_NIST_P384
# if ECC_NIST_P521
const TPMBN_ECC_CURVE_CONSTANTS NIST_P521 = {TPM_ECC_NIST_P521,
(bigNum)&NIST_P521_p,
(bigNum)&NIST_P521_n,
(bigNum)&NIST_P521_h,
(bigNum)&NIST_P521_a,
(bigNum)&NIST_P521_b,
{(bigNum)&NIST_P521_gX,
(bigNum)&NIST_P521_gY,
(bigNum)&NIST_P521_gZ}};
# endif // ECC_NIST_P521
# if ECC_BN_P256
const TPMBN_ECC_CURVE_CONSTANTS BN_P256 = {TPM_ECC_BN_P256,
(bigNum)&BN_P256_p,
(bigNum)&BN_P256_n,
(bigNum)&BN_P256_h,
(bigNum)&BN_P256_a,
(bigNum)&BN_P256_b,
{(bigNum)&BN_P256_gX,
(bigNum)&BN_P256_gY,
(bigNum)&BN_P256_gZ}};
# endif // ECC_BN_P256
# if ECC_BN_P638
const TPMBN_ECC_CURVE_CONSTANTS BN_P638 = {TPM_ECC_BN_P638,
(bigNum)&BN_P638_p,
(bigNum)&BN_P638_n,
(bigNum)&BN_P638_h,
(bigNum)&BN_P638_a,
(bigNum)&BN_P638_b,
{(bigNum)&BN_P638_gX,
(bigNum)&BN_P638_gY,
(bigNum)&BN_P638_gZ}};
# endif // ECC_BN_P638
# if ECC_SM2_P256
const TPMBN_ECC_CURVE_CONSTANTS SM2_P256 = {TPM_ECC_SM2_P256,
(bigNum)&SM2_P256_p,
(bigNum)&SM2_P256_n,
(bigNum)&SM2_P256_h,
(bigNum)&SM2_P256_a,
(bigNum)&SM2_P256_b,
{(bigNum)&SM2_P256_gX,
(bigNum)&SM2_P256_gY,
(bigNum)&SM2_P256_gZ}};
# endif // ECC_SM2_P256
# define comma
const TPMBN_ECC_CURVE_CONSTANTS* bnEccCurveData[] = {
# if ECC_NIST_P192
&NIST_P192,
# endif
# if ECC_NIST_P224
&NIST_P224,
# endif
# if ECC_NIST_P256
&NIST_P256,
# endif
# if ECC_NIST_P384
&NIST_P384,
# endif
# if ECC_NIST_P521
&NIST_P521,
# endif
# if ECC_BN_P256
&BN_P256,
# endif
# if ECC_BN_P638
&BN_P638,
# endif
# if ECC_SM2_P256
&SM2_P256,
# endif
};
MUST_BE((sizeof(bnEccCurveData) / sizeof(bnEccCurveData[0])) == (ECC_CURVE_COUNT));
//*** BnGetCurveData()
// This function returns the pointer for the constant parameter data
// associated with a curve.
const TPMBN_ECC_CURVE_CONSTANTS* BnGetCurveData(TPM_ECC_CURVE curveId)
{
for(int i = 0; i < ECC_CURVE_COUNT; i++)
{
if(bnEccCurveData[i]->curveId == curveId)
return bnEccCurveData[i];
}
return NULL;
}
#endif // TPM_ALG_ECC

View File

@ -507,6 +507,41 @@ LIB_EXPORT BOOL BnShiftRight(bigNum result, bigConst toShift, uint32_t shiftAmou
BnSetTop(result, finalSize);
return TRUE;
}
//*** BnIsPointOnCurve()
// This function checks if a point is on the curve.
BOOL BnIsPointOnCurve(pointConst Q, const TPMBN_ECC_CURVE_CONSTANTS* C)
{
BN_VAR(right, (MAX_ECC_KEY_BITS * 3));
BN_VAR(left, (MAX_ECC_KEY_BITS * 2));
bigConst prime = BnCurveGetPrime(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, BnCurveGet_a(C));
// ExtMath_Mod(right, CurveGetPrime(C));
// x(x^2 + a)
BnMult(right, right, Q->x);
// x(x^2 + a) + b
BnAdd(right, right, BnCurveGet_b(C));
BnMod(right, prime);
if(BnUnsignedCmp(left, right) == 0)
return TRUE;
else
return FALSE;
}
/* 10.2.3.3.20 BnGetRandomBits() */
/* Return Value Meaning */
/* TRUE(1) success */

View File

@ -133,18 +133,19 @@ LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus);
// structure is a set of pointers to bigNum values. The curve-dependent values are
// set by a different function. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT bigCurve BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId);
LIB_EXPORT bigCurveData* BnCurveInitialize(bigCurveData* E, TPM_ECC_CURVE curveId);
//*** 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);
LIB_EXPORT void BnCurveFree(bigCurveData* E);
//** BnEccModMult()
// This function does a point multiply of the form R = [d]S. A return of FALSE
// indicates that the result was the point at infinity. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT BOOL BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E);
LIB_EXPORT BOOL BnEccModMult(
bigPoint R, pointConst S, bigConst d, const bigCurveData* E);
//** BnEccModMult2()
// This function does a point multiply of the form R = [d]S + [u]Q. A return of
@ -155,15 +156,23 @@ LIB_EXPORT BOOL BnEccModMult2(bigPoint R,
bigConst d,
pointConst Q,
bigConst u,
const bigCurve E);
const bigCurveData* E);
//** BnEccAdd()
// This function does a point add R = S + Q. A return of FALSE
// indicates that the result was the point at infinity. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT BOOL BnEccAdd(
bigPoint R, pointConst S, pointConst Q, const bigCurve E);
bigPoint R, pointConst S, pointConst Q, const bigCurveData* E);
#endif // ALG_ECC
// libtpms: added begin
bigCurveData*
BnCurveInitialize(
bigCurveData* E, // IN: curve structure to initialize
TPM_ECC_CURVE curveId // IN: curve identifier
);
// libtpms: added end
#endif //BN_SUPPORT_INTERFACE_H

View File

@ -73,550 +73,79 @@
// The CURVE_NAME macro is used to remove the name string from normal builds, but leaves the
// string available in the initialization lists for potenial use during debugging by changing this
// macro (and the structure declaration)
#if USE_BN_ECC_DATA
# define TO_ECC_64 TO_CRYPT_WORD_64
# define TO_ECC_56(a, b, c, d, e, f, g) TO_ECC_64(0, a, b, c, d, e, f, g)
# define TO_ECC_48(a, b, c, d, e, f) TO_ECC_64(0, 0, a, b, c, d, e, f)
# define TO_ECC_40(a, b, c, d, e) TO_ECC_64(0, 0, 0, a, b, c, d, e)
# if RADIX_BITS > 32
# define TO_ECC_32(a, b, c, d) TO_ECC_64(0, 0, 0, 0, a, b, c, d)
# define TO_ECC_24(a, b, c) TO_ECC_64(0, 0, 0, 0, 0, a, b, c)
# define TO_ECC_16(a, b) TO_ECC_64(0, 0, 0, 0, 0, 0, a, b)
# define TO_ECC_8(a) TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a)
# else // RADIX_BITS == 32
# define TO_ECC_32 BIG_ENDIAN_BYTES_TO_UINT32
# define TO_ECC_24(a, b, c) TO_ECC_32(0, a, b, c)
# define TO_ECC_16(a, b) TO_ECC_32(0, 0, a, b)
# define TO_ECC_8(a) TO_ECC_32(0, 0, 0, a)
# endif
#else // TPM2B_
# define TO_ECC_64(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h
# define TO_ECC_56(a, b, c, d, e, f, g) a, b, c, d, e, f, g
# define TO_ECC_48(a, b, c, d, e, f) a, b, c, d, e, f
# define TO_ECC_40(a, b, c, d, e) a, b, c, d, e
# define TO_ECC_32(a, b, c, d) a, b, c, d
# define TO_ECC_24(a, b, c) a, b, c
# define TO_ECC_16(a, b) a, b
# define TO_ECC_8(a) a
#endif
#if USE_BN_ECC_DATA
#define BN_MIN_ALLOC(bytes) \
(BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes)
# define ECC_CONST(NAME, bytes, initializer) \
const struct { \
crypt_uword_t allocate, size, d[BN_MIN_ALLOC(bytes)]; \
} NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes),{initializer}}
ECC_CONST(ECC_ZERO, 0, 0);
#else
# define ECC_CONST(NAME, bytes, initializer) \
const TPM2B_##bytes##_BYTE_VALUE NAME = {bytes, {initializer}}
/* Have to special case ECC_ZERO */
TPM2B_BYTE_VALUE(1);
TPM2B_1_BYTE_VALUE ECC_ZERO = {1, {0}};
#endif
ECC_CONST(ECC_ONE, 1, 1);
#if !USE_BN_ECC_DATA
TPM2B_BYTE_VALUE(24);
#define TO_ECC_192(a, b, c) a, b, c
TPM2B_BYTE_VALUE(28);
#define TO_ECC_224(a, b, c, d) a, b, c, d
TPM2B_BYTE_VALUE(32);
#define TO_ECC_256(a, b, c, d) a, b, c, d
TPM2B_BYTE_VALUE(48);
#define TO_ECC_384(a, b, c, d, e, f) a, b, c, d, e, f
TPM2B_BYTE_VALUE(66);
#define TO_ECC_528(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i
TPM2B_BYTE_VALUE(80);
#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j
#else
#define TO_ECC_192(a, b, c) c, b, a
#define TO_ECC_224(a, b, c, d) d, c, b, a
#define TO_ECC_256(a, b, c, d) d, c, b, a
#define TO_ECC_384(a, b, c, d, e, f) f, e, d, c, b, a
#define TO_ECC_528(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a
#define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a
#endif // !USE_BN_ECC_DATA
#if ECC_NIST_P192
ECC_CONST(NIST_P192_p, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P192_a, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P192_b, 24, TO_ECC_192(
TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7),
TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49),
TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1)));
ECC_CONST(NIST_P192_gX, 24, TO_ECC_192(
TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6),
TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00),
TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12)));
ECC_CONST(NIST_P192_gY, 24, TO_ECC_192(
TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78),
TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5),
TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11)));
ECC_CONST(NIST_P192_n, 24, TO_ECC_192(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36),
TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31)));
#define NIST_P192_h ECC_ONE
#define NIST_P192_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P192 = {
(bigNum)&NIST_P192_p, (bigNum)&NIST_P192_n, (bigNum)&NIST_P192_h,
(bigNum)&NIST_P192_a, (bigNum)&NIST_P192_b,
{(bigNum)&NIST_P192_gX, (bigNum)&NIST_P192_gY, (bigNum)&NIST_P192_gZ}};
#else
const ECC_CURVE_DATA NIST_P192 = {
&NIST_P192_p.b, &NIST_P192_n.b, &NIST_P192_h.b,
&NIST_P192_a.b, &NIST_P192_b.b,
{&NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_NIST_P192
#if ECC_NIST_P224
ECC_CONST(NIST_P224_p, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01)));
ECC_CONST(NIST_P224_a, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE)));
ECC_CONST(NIST_P224_b, 28, TO_ECC_224(
TO_ECC_32(0xB4, 0x05, 0x0A, 0x85),
TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56),
TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA),
TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4)));
ECC_CONST(NIST_P224_gX, 28, TO_ECC_224(
TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD),
TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9),
TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22),
TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21)));
ECC_CONST(NIST_P224_gY, 28, TO_ECC_224(
TO_ECC_32(0xBD, 0x37, 0x63, 0x88),
TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6),
TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64),
TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34)));
ECC_CONST(NIST_P224_n, 28, TO_ECC_224(
TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E),
TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D)));
#define NIST_P224_h ECC_ONE
#define NIST_P224_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P224 = {
(bigNum)&NIST_P224_p, (bigNum)&NIST_P224_n, (bigNum)&NIST_P224_h,
(bigNum)&NIST_P224_a, (bigNum)&NIST_P224_b,
{(bigNum)&NIST_P224_gX, (bigNum)&NIST_P224_gY, (bigNum)&NIST_P224_gZ}};
#else
const ECC_CURVE_DATA NIST_P224 = {
&NIST_P224_p.b, &NIST_P224_n.b, &NIST_P224_h.b,
&NIST_P224_a.b, &NIST_P224_b.b,
{&NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_NIST_P224
#if ECC_NIST_P256
ECC_CONST(NIST_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P256_a, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P256_b, 32, TO_ECC_256(
TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7),
TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC),
TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6),
TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B)));
ECC_CONST(NIST_P256_gX, 32, TO_ECC_256(
TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47),
TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2),
TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0),
TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96)));
ECC_CONST(NIST_P256_gY, 32, TO_ECC_256(
TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B),
TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16),
TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE),
TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5)));
ECC_CONST(NIST_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84),
TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51)));
#define NIST_P256_h ECC_ONE
#define NIST_P256_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P256 = {
(bigNum)&NIST_P256_p, (bigNum)&NIST_P256_n, (bigNum)&NIST_P256_h,
(bigNum)&NIST_P256_a, (bigNum)&NIST_P256_b,
{(bigNum)&NIST_P256_gX, (bigNum)&NIST_P256_gY, (bigNum)&NIST_P256_gZ}};
#else
const ECC_CURVE_DATA NIST_P256 = {
&NIST_P256_p.b, &NIST_P256_n.b, &NIST_P256_h.b,
&NIST_P256_a.b, &NIST_P256_b.b,
{&NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_NIST_P256
#if ECC_NIST_P384
ECC_CONST(NIST_P384_p, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P384_a, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P384_b, 48, TO_ECC_384(
TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4),
TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19),
TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12),
TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A),
TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D),
TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF)));
ECC_CONST(NIST_P384_gX, 48, TO_ECC_384(
TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37),
TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74),
TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98),
TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38),
TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C),
TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7)));
ECC_CONST(NIST_P384_gY, 48, TO_ECC_384(
TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F),
TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29),
TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C),
TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0),
TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D),
TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F)));
ECC_CONST(NIST_P384_n, 48, TO_ECC_384(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF),
TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A),
TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73)));
#define NIST_P384_h ECC_ONE
#define NIST_P384_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P384 = {
(bigNum)&NIST_P384_p, (bigNum)&NIST_P384_n, (bigNum)&NIST_P384_h,
(bigNum)&NIST_P384_a, (bigNum)&NIST_P384_b,
{(bigNum)&NIST_P384_gX, (bigNum)&NIST_P384_gY, (bigNum)&NIST_P384_gZ}};
#else
const ECC_CURVE_DATA NIST_P384 = {
&NIST_P384_p.b, &NIST_P384_n.b, &NIST_P384_h.b,
&NIST_P384_a.b, &NIST_P384_b.b,
{&NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_NIST_P384
#if ECC_NIST_P521
ECC_CONST(NIST_P521_p, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P521_a, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P521_b, 66, TO_ECC_528(
TO_ECC_16(0x00, 0x51),
TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F),
TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE),
TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3),
TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1),
TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B),
TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07),
TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1),
TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00)));
ECC_CONST(NIST_P521_gX, 66, TO_ECC_528(
TO_ECC_16(0x00, 0xC6),
TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD),
TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42),
TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21),
TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA),
TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28),
TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE),
TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B),
TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66)));
ECC_CONST(NIST_P521_gY, 66, TO_ECC_528(
TO_ECC_16(0x01, 0x18),
TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04),
TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9),
TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68),
TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C),
TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40),
TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61),
TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40),
TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50)));
ECC_CONST(NIST_P521_n, 66, TO_ECC_528(
TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA),
TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B),
TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0),
TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE),
TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09)));
#define NIST_P521_h ECC_ONE
#define NIST_P521_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA NIST_P521 = {
(bigNum)&NIST_P521_p, (bigNum)&NIST_P521_n, (bigNum)&NIST_P521_h,
(bigNum)&NIST_P521_a, (bigNum)&NIST_P521_b,
{(bigNum)&NIST_P521_gX, (bigNum)&NIST_P521_gY, (bigNum)&NIST_P521_gZ}};
#else
const ECC_CURVE_DATA NIST_P521 = {
&NIST_P521_p.b, &NIST_P521_n.b, &NIST_P521_h.b,
&NIST_P521_a.b, &NIST_P521_b.b,
{&NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_NIST_P521
#if ECC_BN_P256
ECC_CONST(BN_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82),
TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13)));
#define BN_P256_a ECC_ZERO
ECC_CONST(BN_P256_b, 1, TO_ECC_8(3));
#define BN_P256_gX ECC_ONE
ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2));
ECC_CONST(BN_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A),
TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D)));
#define BN_P256_h ECC_ONE
#define BN_P256_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA BN_P256 = {
(bigNum)&BN_P256_p, (bigNum)&BN_P256_n, (bigNum)&BN_P256_h,
(bigNum)&BN_P256_a, (bigNum)&BN_P256_b,
{(bigNum)&BN_P256_gX, (bigNum)&BN_P256_gY, (bigNum)&BN_P256_gZ}};
#else
const ECC_CURVE_DATA BN_P256 = {
&BN_P256_p.b, &BN_P256_n.b, &BN_P256_h.b,
&BN_P256_a.b, &BN_P256_b.b,
{&BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_BN_P256
#if ECC_BN_P638
ECC_CONST(BN_P638_p, 80, TO_ECC_640(
TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67)));
#define BN_P638_a ECC_ZERO
ECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01,0x01));
ECC_CONST(BN_P638_gX, 80, TO_ECC_640(
TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66)));
ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10));
ECC_CONST(BN_P638_n, 80, TO_ECC_640(
TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0),
TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61)));
#define BN_P638_h ECC_ONE
#define BN_P638_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA BN_P638 = {
(bigNum)&BN_P638_p, (bigNum)&BN_P638_n, (bigNum)&BN_P638_h,
(bigNum)&BN_P638_a, (bigNum)&BN_P638_b,
{(bigNum)&BN_P638_gX, (bigNum)&BN_P638_gY, (bigNum)&BN_P638_gZ}};
#else
const ECC_CURVE_DATA BN_P638 = {
&BN_P638_p.b, &BN_P638_n.b, &BN_P638_h.b,
&BN_P638_a.b, &BN_P638_b.b,
{&BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_BN_P638
#if ECC_SM2_P256
ECC_CONST(SM2_P256_p, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(SM2_P256_a, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(SM2_P256_b, 32, TO_ECC_256(
TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34),
TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7),
TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92),
TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93)));
ECC_CONST(SM2_P256_gX, 32, TO_ECC_256(
TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19),
TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94),
TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1),
TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7)));
ECC_CONST(SM2_P256_gY, 32, TO_ECC_256(
TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C),
TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53),
TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40),
TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0)));
ECC_CONST(SM2_P256_n, 32, TO_ECC_256(
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B),
TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23)));
#define SM2_P256_h ECC_ONE
#define SM2_P256_gZ ECC_ONE
#if USE_BN_ECC_DATA
const ECC_CURVE_DATA SM2_P256 = {
(bigNum)&SM2_P256_p, (bigNum)&SM2_P256_n, (bigNum)&SM2_P256_h,
(bigNum)&SM2_P256_a, (bigNum)&SM2_P256_b,
{(bigNum)&SM2_P256_gX, (bigNum)&SM2_P256_gY, (bigNum)&SM2_P256_gZ}};
#else
const ECC_CURVE_DATA SM2_P256 = {
&SM2_P256_p.b, &SM2_P256_n.b, &SM2_P256_h.b,
&SM2_P256_a.b, &SM2_P256_b.b,
{&SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_gZ.b}};
#endif // USE_BN_ECC_DATA
#endif // ECC_SM2_P256
# define CURVE_NAME(N)
# define comma
const ECC_CURVE eccCurves[] = {
const TPM_ECC_CURVE_METADATA eccCurves[] = {
# if ECC_NIST_P192
comma
{TPM_ECC_NIST_P192,
192,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&NIST_P192,
OID_ECC_NIST_P192
CURVE_NAME("NIST_P192")}
comma{TPM_ECC_NIST_P192,
192,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_NIST_P192 CURVE_NAME("NIST_P192")}
# undef comma
# define comma ,
# endif // ECC_NIST_P192
# if ECC_NIST_P224
comma
{TPM_ECC_NIST_P224,
224,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&NIST_P224,
OID_ECC_NIST_P224
CURVE_NAME("NIST_P224")}
comma{TPM_ECC_NIST_P224,
224,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_NIST_P224 CURVE_NAME("NIST_P224")}
# undef comma
# define comma ,
# endif // ECC_NIST_P224
# if ECC_NIST_P256
comma
{TPM_ECC_NIST_P256,
256,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&NIST_P256,
OID_ECC_NIST_P256
CURVE_NAME("NIST_P256")}
comma{TPM_ECC_NIST_P256,
256,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_NIST_P256 CURVE_NAME("NIST_P256")}
# undef comma
# define comma ,
# endif // ECC_NIST_P256
# if ECC_NIST_P384
comma
{TPM_ECC_NIST_P384,
384,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&NIST_P384,
OID_ECC_NIST_P384
CURVE_NAME("NIST_P384")}
comma{TPM_ECC_NIST_P384,
384,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_NIST_P384 CURVE_NAME("NIST_P384")}
# undef comma
# define comma ,
# endif // ECC_NIST_P384
# if ECC_NIST_P521
comma
{TPM_ECC_NIST_P521,
521,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&NIST_P521,
OID_ECC_NIST_P521
CURVE_NAME("NIST_P521")}
comma{TPM_ECC_NIST_P521,
521,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_NIST_P521 CURVE_NAME("NIST_P521")}
# undef comma
# define comma ,
# endif // ECC_NIST_P521
# if ECC_BN_P256
comma
{TPM_ECC_BN_P256,
256,
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&BN_P256,
OID_ECC_BN_P256
CURVE_NAME("BN_P256")}
comma{TPM_ECC_BN_P256,
256,
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_BN_P256 CURVE_NAME("BN_P256")}
# undef comma
# define comma ,
# endif // ECC_BN_P256
# if ECC_BN_P638
comma
{TPM_ECC_BN_P638,
638,
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&BN_P638,
OID_ECC_BN_P638
CURVE_NAME("BN_P638")}
comma{TPM_ECC_BN_P638,
638,
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_BN_P638 CURVE_NAME("BN_P638")}
# undef comma
# define comma ,
# endif // ECC_BN_P638
# if ECC_SM2_P256
comma
{TPM_ECC_SM2_P256,
256,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
&SM2_P256,
OID_ECC_SM2_P256
CURVE_NAME("SM2_P256")}
comma{TPM_ECC_SM2_P256,
256,
{TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}},
{TPM_ALG_NULL, {{TPM_ALG_NULL}}},
OID_ECC_SM2_P256 CURVE_NAME("SM2_P256")}
# undef comma
# define comma ,
# endif // ECC_SM2_P256

View File

@ -0,0 +1,474 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
/* Microsoft Reference Implementation for TPM 2.0
*
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and
* contributor rights, including patent rights, and no such rights are granted
* under this license.
*
* Copyright (c) Microsoft Corporation
*
* All rights reserved.
*
* BSD License
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This file contains the ECC curve data. The data is contained in macros so this
// file can be included in other format-specific header files that reformat the
// constant data in any format desired. This file itself is never used alone.
// Expected macros:
//
// TO_ECC_<bits>:
// <bits> <= 64:
// "N" byte arguments in most-significant to least-significant order The number
// of arguments depends on the bit length, which must be a multiple of 8.
// <bits> > 64:
// "Q" macro arguments from the <bits> <= 64 group to produce the total number
// of requested bits.
//
// ECC_CONST:
// Parameters:
// Name, Bytes, initial value; either a single byte value or a combination of TO_ECC macros
#if ALG_ECC
ECC_CONST(ECC_ZERO, 1, 0);
ECC_CONST(ECC_ONE, 1, 1);
# if ECC_NIST_P192
ECC_CONST(NIST_P192_p,
24,
TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P192_a,
24,
TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P192_b,
24,
TO_ECC_192(TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7),
TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49),
TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1)));
ECC_CONST(NIST_P192_gX,
24,
TO_ECC_192(TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6),
TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00),
TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12)));
ECC_CONST(NIST_P192_gY,
24,
TO_ECC_192(TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78),
TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5),
TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11)));
ECC_CONST(NIST_P192_n,
24,
TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36),
TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31)));
# define NIST_P192_h ECC_ONE
# define NIST_P192_gZ ECC_ONE
# endif // ECC_NIST_P192
# if ECC_NIST_P224
ECC_CONST(NIST_P224_p,
28,
TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01)));
ECC_CONST(NIST_P224_a,
28,
TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE)));
ECC_CONST(NIST_P224_b,
28,
TO_ECC_224(TO_ECC_32(0xB4, 0x05, 0x0A, 0x85),
TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56),
TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA),
TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4)));
ECC_CONST(NIST_P224_gX,
28,
TO_ECC_224(TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD),
TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9),
TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22),
TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21)));
ECC_CONST(NIST_P224_gY,
28,
TO_ECC_224(TO_ECC_32(0xBD, 0x37, 0x63, 0x88),
TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6),
TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64),
TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34)));
ECC_CONST(NIST_P224_n,
28,
TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E),
TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D)));
# define NIST_P224_h ECC_ONE
# define NIST_P224_gZ ECC_ONE
# endif // ECC_NIST_P224
# if ECC_NIST_P256
ECC_CONST(NIST_P256_p,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P256_a,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P256_b,
32,
TO_ECC_256(TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7),
TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC),
TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6),
TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B)));
ECC_CONST(NIST_P256_gX,
32,
TO_ECC_256(TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47),
TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2),
TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0),
TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96)));
ECC_CONST(NIST_P256_gY,
32,
TO_ECC_256(TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B),
TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16),
TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE),
TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5)));
ECC_CONST(NIST_P256_n,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84),
TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51)));
# define NIST_P256_h ECC_ONE
# define NIST_P256_gZ ECC_ONE
# endif // ECC_NIST_P256
# if ECC_NIST_P384
ECC_CONST(NIST_P384_p,
48,
TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P384_a,
48,
TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P384_b,
48,
TO_ECC_384(TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4),
TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19),
TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12),
TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A),
TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D),
TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF)));
ECC_CONST(NIST_P384_gX,
48,
TO_ECC_384(TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37),
TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74),
TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98),
TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38),
TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C),
TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7)));
ECC_CONST(NIST_P384_gY,
48,
TO_ECC_384(TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F),
TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29),
TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C),
TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0),
TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D),
TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F)));
ECC_CONST(NIST_P384_n,
48,
TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF),
TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A),
TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73)));
# define NIST_P384_h ECC_ONE
# define NIST_P384_gZ ECC_ONE
# endif // ECC_NIST_P384
# if ECC_NIST_P521
ECC_CONST(NIST_P521_p,
66,
TO_ECC_528(TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(NIST_P521_a,
66,
TO_ECC_528(TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(NIST_P521_b,
66,
TO_ECC_528(TO_ECC_16(0x00, 0x51),
TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F),
TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE),
TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3),
TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1),
TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B),
TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07),
TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1),
TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00)));
ECC_CONST(NIST_P521_gX,
66,
TO_ECC_528(TO_ECC_16(0x00, 0xC6),
TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD),
TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42),
TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21),
TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA),
TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28),
TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE),
TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B),
TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66)));
ECC_CONST(NIST_P521_gY,
66,
TO_ECC_528(TO_ECC_16(0x01, 0x18),
TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04),
TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9),
TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68),
TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C),
TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40),
TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61),
TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40),
TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50)));
ECC_CONST(NIST_P521_n,
66,
TO_ECC_528(TO_ECC_16(0x01, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA),
TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B),
TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0),
TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE),
TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09)));
# define NIST_P521_h ECC_ONE
# define NIST_P521_gZ ECC_ONE
# endif // ECC_NIST_P521
# if ECC_BN_P256
ECC_CONST(BN_P256_p,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82),
TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13)));
# define BN_P256_a ECC_ZERO
ECC_CONST(BN_P256_b, 1, TO_ECC_8(3));
# define BN_P256_gX ECC_ONE
ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2));
ECC_CONST(BN_P256_n,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD),
TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E),
TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A),
TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D)));
# define BN_P256_h ECC_ONE
# define BN_P256_gZ ECC_ONE
# endif // ECC_BN_P256
# if ECC_BN_P638
ECC_CONST(BN_P638_p,
80,
TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67)));
# define BN_P638_a ECC_ZERO
ECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01, 0x01));
ECC_CONST(BN_P638_gX,
80,
TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80),
TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66)));
ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10));
ECC_CONST(BN_P638_n,
80,
TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D),
TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3),
TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E),
TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F),
TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55),
TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55),
TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0),
TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0),
TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61)));
# define BN_P638_h ECC_ONE
# define BN_P638_gZ ECC_ONE
# endif // ECC_BN_P638
# if ECC_SM2_P256
ECC_CONST(SM2_P256_p,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)));
ECC_CONST(SM2_P256_a,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC)));
ECC_CONST(SM2_P256_b,
32,
TO_ECC_256(TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34),
TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7),
TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92),
TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93)));
ECC_CONST(SM2_P256_gX,
32,
TO_ECC_256(TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19),
TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94),
TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1),
TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7)));
ECC_CONST(SM2_P256_gY,
32,
TO_ECC_256(TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C),
TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53),
TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40),
TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0)));
ECC_CONST(SM2_P256_n,
32,
TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B),
TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23)));
# define SM2_P256_h ECC_ONE
# define SM2_P256_gZ ECC_ONE
# endif // ECC_SM2_P256
#endif // TPM_ALG_ECC

View File

@ -60,6 +60,7 @@
#include "Tpm.h"
#include "Commit_fp.h"
#include "TpmMath_Util_fp.h"
#if CC_Commit // Conditional expansion of this file
@ -115,7 +116,7 @@ TPM2_Commit(Commit_In* in, // IN: input parameter list
// Get prime modulus for the curve. This is needed later but getting this now
// allows confirmation that the curve exists.
if(!CryptEccGetParameter(&p, 'p', parms->curveID))
if(!TpmMath_IntTo2B(ExtEcc_CurveGetPrime(parms->curveID), &p.b, 0))
return TPM_RCS_KEY + RC_Commit_signHandle;
// Get the random value that will be used in the point multiplications

View File

@ -116,7 +116,6 @@
#include "CryptHash_fp.h"
#include "CryptSym_fp.h"
#include "CryptDes_fp.h"
#include "TpmToTpmBigNumMath.h" // libtpms: temp
#include "CryptPrime_fp.h"
#include "CryptRand_fp.h"
#include "CryptSelfTest_fp.h"
@ -147,6 +146,4 @@
// TODO_RENAME_INC_FOLDER:platform_interface refers to the TPM_CoreLib platform interface
#include "tpm_to_platform_interface.h"
#include "TpmMath_Util_fp.h" // libtpms: temporary
#endif

View File

@ -179,6 +179,13 @@ LIB_EXPORT BOOL ExtMath_SubtractWord(
// Modular Arithmetic, writ large
// ###############################
//** ExtMath_Mod()
// compute valueAndResult = valueAndResult mod modulus
// This function divides two Crypt_Int* values and returns only the remainder,
// replacing the original dividend. The function returns FALSE if there is an
// error in the operation.
LIB_EXPORT BOOL ExtMath_Mod(Crypt_Int* valueAndResult, const Crypt_Int* modulus);
//** ExtMath_ModMult()
// Compute result = (op1 * op2) mod modulus
LIB_EXPORT BOOL ExtMath_ModMult(Crypt_Int* result,
@ -202,6 +209,17 @@ LIB_EXPORT BOOL ExtMath_ModExp(Crypt_Int* result,
LIB_EXPORT BOOL ExtMath_ModInverse(
Crypt_Int* result, const Crypt_Int* number, const Crypt_Int* modulus);
//** ExtMath_ModInversePrime()
// Compute the modular multiplicative inverse. This is an optimized function for
// the case where the modulus is known to be prime.
//
// CAUTION: Depending on the library implementation this may be much faster than
// the normal ModInverse, and therefore is subject to exposing the fact the
// modulus is prime via a timing side-channel. In many cases (e.g. ECC primes),
// the prime is not sensitive and this optimized route can be used.
LIB_EXPORT BOOL ExtMath_ModInversePrime(
Crypt_Int* result, const Crypt_Int* number, const Crypt_Int* primeModulus);
//*** ExtMath_ModWord()
// compute numerator
// This function does modular division of a big number when the modulus is a
@ -270,6 +288,17 @@ LIB_EXPORT unsigned ExtMath_SizeInBits(const Crypt_Int* n);
// Bitwise Operations
// ###############################
//*** ExtMath_SetBit()
//
// This function will SET a bit in a Crypt_Int*. Bit 0 is the least-significant
// bit in the 0th digit_t. The function returns TRUE if the bitNum is within the
// range valid for the given number. If bitNum is too large, the function
// should return FALSE, and the TPM will enter failure mode.
// Return Type: BOOL
LIB_EXPORT BOOL ExtMath_SetBit(Crypt_Int* bn, // IN/OUT: big number to modify
unsigned int bitNum // IN: Bit number to SET
);
//*** ExtMath_TestBit()
// This function is used to check to see if a bit is SET in a bignum_t. The 0th bit
// is the LSb of d[0].
@ -280,10 +309,125 @@ LIB_EXPORT BOOL ExtMath_TestBit(Crypt_Int* bn, // IN: number to check
unsigned int bitNum // IN: bit to test
);
//***ExtMath_MaskBits()
// This function is used to mask off high order bits of a big number.
// The returned value will have no more than 'maskBit' bits
// set.
// Note: There is a requirement that unused words of a bignum_t are set to zero.
// Return Type: BOOL
// TRUE(1) result masked
// FALSE(0) the input was not as large as the mask
LIB_EXPORT BOOL ExtMath_MaskBits(
Crypt_Int* bn, // IN/OUT: number to mask
crypt_uword_t maskBit // IN: the bit number for the mask.
);
//*** ExtMath_ShiftRight()
// This function will shift a Crypt_Int* to the right by the shiftAmount.
// This function always returns TRUE.
LIB_EXPORT BOOL ExtMath_ShiftRight(
Crypt_Int* result, const Crypt_Int* toShift, uint32_t shiftAmount);
// ***************************************************************************
// ECC Functions
// ***************************************************************************
// #################
// type initializers
// #################
//** initialize point structure given memory size of each coordinate
LIB_EXPORT Crypt_Point* ExtEcc_Initialize_Point(Crypt_Point* buffer,
NUMBYTES bitsPerCoord);
//** ExtEcc_CurveInitialize()
// This function is used to initialize a Crypt_EccCurve structure. The
// structure is a set of pointers to Crypt_Int* values. The curve-dependent values are
// set by a different function. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT const Crypt_EccCurve* ExtEcc_CurveInitialize(Crypt_EccCurve* E,
TPM_ECC_CURVE curveId);
// #################
// DESTRUCTOR - See Warning
// #################
//*** ExtEcc_CurveFree()
// This function will free the allocated components of the curve and end the
// frame in which the curve data exists.
// WARNING: Not guaranteed to be called in presence of LONGJMP.
LIB_EXPORT void ExtEcc_CurveFree(const Crypt_EccCurve* E);
// #################
// Buffer Converters
// #################
//** point structure to/from raw coordinate buffers.
LIB_EXPORT Crypt_Point* ExtEcc_PointFromBytes(Crypt_Point* buffer,
const BYTE* x,
NUMBYTES nBytesX,
const BYTE* y,
NUMBYTES nBytesY);
LIB_EXPORT BOOL ExtEcc_PointToBytes(
const Crypt_Point* point, BYTE* x, NUMBYTES* nBytesX, BYTE* y, NUMBYTES* nBytesY);
// ####################
// ECC Point Operations
// ####################
//** ExtEcc_PointMultiply()
// This function does a point multiply of the form R = [d]S. A return of FALSE
// indicates that the result was the point at infinity. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT BOOL ExtEcc_PointMultiply(Crypt_Point* R,
const Crypt_Point* S,
const Crypt_Int* d,
const Crypt_EccCurve* E);
//** ExtEcc_PointMultiplyAndAdd()
// This function does a point multiply of the form R = [d]S + [u]Q. A return of
// FALSE indicates that the result was the point at infinity. This function is only
// needed if the TPM supports ECC.
LIB_EXPORT BOOL ExtEcc_PointMultiplyAndAdd(Crypt_Point* R,
const Crypt_Point* S,
const Crypt_Int* d,
const Crypt_Point* Q,
const Crypt_Int* u,
const Crypt_EccCurve* E);
//** ExtEcc_PointAdd()
// This function does a point add R = S + Q. A return of FALSE
// indicates that the result was the point at infinity. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT BOOL ExtEcc_PointAdd(Crypt_Point* R,
const Crypt_Point* S,
const Crypt_Point* Q,
const Crypt_EccCurve* E);
// #####################
// ECC Point Information
// #####################
LIB_EXPORT BOOL ExtEcc_IsPointOnCurve(const Crypt_Point* Q, const Crypt_EccCurve* E);
LIB_EXPORT BOOL ExtEcc_IsInfinityPoint(const Crypt_Point* pt);
// extract the X-Coordinate of a point
LIB_EXPORT const Crypt_Int* ExtEcc_PointX(const Crypt_Point* pt);
// extract the Y-Coordinate of a point
// (no current use case for the Y coordinate alone, signatures use X)
// LIB_EXPORT const Crypt_Int* ExtEcc_PointY(const Crypt_Point* pt);
// #####################
// ECC Curve Information
// #####################
// These functions are expected to be fast, returning pre-built constants without
// allocation or copying.
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetPrime(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetOrder(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetCofactor(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGet_a(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGet_b(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Point* ExtEcc_CurveGetG(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetGx(TPM_ECC_CURVE curveId);
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetGy(TPM_ECC_CURVE curveId);
LIB_EXPORT TPM_ECC_CURVE ExtEcc_CurveGetCurveId(const Crypt_EccCurve* E);
#endif

View File

@ -70,12 +70,20 @@
#ifndef CRYPT_INT_BUF
# error CRYPT_INT_BUF must be defined before including this file.
#endif
#ifndef CRYPT_POINT_BUF
# error CRYPT_POINT_BUF must be defined before including this file.
#endif
#ifndef CRYPT_CURVE_BUF
# error CRYPT_CURVE_BUF must be defined before including this file.
#endif
// Crypt_Int underlying types Crypt_Int is an abstract type that is used as a
// pointer. The underlying math library is expected to be able to find the
// actual allocated size for a given Crypt_Int object given a pointer to it, and
// therefore we typedef here to a size 1 (smallest possible).
typedef CRYPT_INT_BUF(one, 1) Crypt_Int;
typedef CRYPT_POINT_BUF(pointone, 1) Crypt_Point;
typedef CRYPT_CURVE_BUF(curvebuft, MAX_ECC_KEY_BITS) Crypt_EccCurve;
// produces bare typedef ci_<typename>_t
#define CRYPT_INT_TYPE(typename, bits) \
@ -106,5 +114,32 @@ typedef CRYPT_INT_BUF(one, 1) Crypt_Int;
// A single RADIX_BITS value.
#define CRYPT_INT_WORD(name) CRYPT_INT_VAR(name, RADIX_BITS)
#define CRYPT_INT_WORD_INITIALIZED(varname, initializer) \
CRYPT_INT_BUF(cibuf##varname, RADIX_BITS) varname##_buf; \
Crypt_Int* varname = ExtMath_SetWord( \
ExtMath_Initialize_Int((Crypt_Int*)&(varname##_buf), RADIX_BITS), \
initializer);
// Crypt_EccCurve underlying types
#define CRYPT_CURVE_INITIALIZED(varname, initializer) \
CRYPT_CURVE_BUF(cv##varname, MAX_ECC_KEY_BITS) varname##_buf; \
const Crypt_EccCurve* varname = \
ExtEcc_CurveInitialize(&(varname##_buf), initializer)
/* no guarantee free will be called in the presence of longjmp */
#define CRYPT_CURVE_FREE(varname) ExtEcc_CurveFree(varname)
#define CRYPT_POINT_VAR(varname) \
CRYPT_POINT_BUF(cp_##varname##_buf_t, MAX_ECC_KEY_BITS) varname##_buf; \
Crypt_Point* varname = \
ExtEcc_Initialize_Point((Crypt_Point*)&(varname##_buf), MAX_ECC_KEY_BITS);
#define CRYPT_POINT_INITIALIZED(varname, initValue) \
CRYPT_POINT_BUF(cp_##varname##_buf_t, MAX_ECC_KEY_BITS) varname##_buf; \
Crypt_Point* varname = TpmEcc_PointFrom2B( \
ExtEcc_Initialize_Point((Crypt_Point*)&(varname##_buf), MAX_ECC_KEY_BITS), \
initValue);
#endif //MATH_LIBRARY_INTERFACE_TYPES_H

View File

@ -150,7 +150,7 @@ LIB_EXPORT BOOL ExtMath_Divide(Crypt_Int* quotient,
(bigNum)quotient, (bigNum)remainder, (bigConst)dividend, (bigConst)divisor);
}
#if ALG_RSA && !RSA_KEY_SIEVE
#if ALG_RSA && !RSA_KEY_SIEVE // libtpms: changed
//** ExtMath_GCD()
// Get the greatest common divisor of two numbers. This function is only needed
// when the TPM implements RSA.
@ -200,6 +200,10 @@ LIB_EXPORT BOOL ExtMath_SubtractWord(
// Modular Arithmetic, writ large
// ###############################
// define Mod in terms of Divide
LIB_EXPORT BOOL ExtMath_Mod(Crypt_Int* valueAndResult, const Crypt_Int* modulus)
{
return ExtMath_Divide(NULL, valueAndResult, valueAndResult, modulus);
}
//** ExtMath_ModMult()
// Does 'op1' * 'op2' and divide by 'modulus' returning the remainder of the divide.
@ -313,6 +317,11 @@ LIB_EXPORT unsigned ExtMath_SizeInBits(const Crypt_Int* n)
// Bitwise Operations
// ###############################
LIB_EXPORT BOOL ExtMath_SetBit(Crypt_Int* bn, unsigned int bitNum)
{
return BnSetBit((bigNum)bn, bitNum);
}
// This function is used to check to see if a bit is SET in a bigNum_t. The 0th bit
//*** ExtMath_TestBit()
// is the LSb of d[0].
@ -326,6 +335,22 @@ LIB_EXPORT BOOL ExtMath_TestBit(Crypt_Int* bn, // IN: number to check
return BnTestBit((bigNum)bn, bitNum);
}
//***ExtMath_MaskBits()
// This function is used to mask off high order bits of a big number.
// The returned value will have no more than 'maskBit' bits
// set.
// Note: There is a requirement that unused words of a bigNum_t are set to zero.
// Return Type: BOOL
// TRUE(1) result masked
// FALSE(0) the input was not as large as the mask
LIB_EXPORT BOOL ExtMath_MaskBits(
Crypt_Int* bn, // IN/OUT: number to mask
crypt_uword_t maskBit // IN: the bit number for the mask.
)
{
return BnMaskBits((bigNum)bn, maskBit);
}
//*** ExtMath_ShiftRight()
// This function will shift a Crypt_Int* to the right by the shiftAmount.
// This function always returns TRUE.
@ -335,3 +360,172 @@ LIB_EXPORT BOOL ExtMath_ShiftRight(
return BnShiftRight((bigNum)result, (bigConst)toShift, shiftAmount);
}
// ***************************************************************************
// ECC Functions
// ***************************************************************************
// ##################
// Point initializers
// ##################
LIB_EXPORT Crypt_Point* ExtEcc_Initialize_Point(Crypt_Point* point, NUMBYTES bitCount)
{
// Since we define the structure, we know that BN_POINT_BUFs are a bn_point_t followed by bignums.
// and that the size is always the MAX_ECC_KEY_SIZE
// tell the individual bignums how large they are:
bn_fullpoint_t* pBuf = (bn_fullpoint_t*)point;
BnInit((bigNum) & (pBuf->x), BN_STRUCT_ALLOCATION(bitCount));
BnInit((bigNum) & (pBuf->y), BN_STRUCT_ALLOCATION(bitCount));
BnInit((bigNum) & (pBuf->z), BN_STRUCT_ALLOCATION(bitCount));
// now feed the addresses of those coordinates to the bn_point_t structure
bn_point_t* bnPoint = (bn_point_t*)point;
BnInitializePoint(
bnPoint, (bigNum) & (pBuf->x), (bigNum) & (pBuf->y), (bigNum) & (pBuf->z));
return point;
}
// ##################
// Curve initializers
// ##################
LIB_EXPORT const Crypt_EccCurve* ExtEcc_CurveInitialize(Crypt_EccCurve* E,
TPM_ECC_CURVE curveId)
{
return BnCurveInitialize((bigCurveData*)E, curveId);
}
// #################
// Curve DESTRUCTOR
// #################
// WARNING: Not guaranteed to be called in presence of LONGJMP.
LIB_EXPORT void ExtEcc_CurveFree(const Crypt_EccCurve* E)
{
BnCurveFree((bigCurveData*)E);
}
// #################
// Buffer Converters
// #################
//*** BnPointFromBytes()
// Function to create a BIG_POINT structure from a 2B point.
// A point is going to be two ECC values in the same buffer. The values are going
// to be the size of the modulus. They are in modular form.
LIB_EXPORT Crypt_Point* ExtEcc_PointFromBytes(Crypt_Point* point,
const BYTE* x,
NUMBYTES nBytesX,
const BYTE* y,
NUMBYTES nBytesY)
{
return (Crypt_Point*)BnPointFromBytes((bigPoint)point, x, nBytesX, y, nBytesY);
}
LIB_EXPORT BOOL ExtEcc_PointToBytes(const Crypt_Point* point,
BYTE* x, NUMBYTES* pBytesX,
BYTE* y, NUMBYTES* pBytesY)
{
return BnPointToBytes((pointConst)point, x, pBytesX, y, pBytesY);
}
// ####################
// ECC Point Operations
// ####################
//** ExtEcc_PointMultiply()
// This function does a point multiply of the form R = [d]S. A return of FALSE
// indicates that the result was the point at infinity. This function is only needed
// if the TPM supports ECC.
LIB_EXPORT BOOL ExtEcc_PointMultiply(
Crypt_Point* R, const Crypt_Point* S, const Crypt_Int* d, const Crypt_EccCurve* E)
{
return BnEccModMult((bigPoint)R, (pointConst)S, (bigConst)d, (bigCurveData*)E);
}
//** ExtEcc_PointMultiplyAndAdd()
// This function does a point multiply of the form R = [d]S + [u]Q. A return of
// FALSE indicates that the result was the point at infinity. This function is only
// needed if the TPM supports ECC.
LIB_EXPORT BOOL ExtEcc_PointMultiplyAndAdd(Crypt_Point* R,
const Crypt_Point* S,
const Crypt_Int* d,
const Crypt_Point* Q,
const Crypt_Int* u,
const Crypt_EccCurve* E)
{
return BnEccModMult2((bigPoint)R,
(pointConst)S,
(bigConst)d,
(pointConst)Q,
(bigConst)u,
(bigCurveData*)E);
}
LIB_EXPORT BOOL ExtEcc_PointAdd(Crypt_Point* R,
const Crypt_Point* S,
const Crypt_Point* Q,
const Crypt_EccCurve* E)
{
return BnEccAdd((bigPoint)R, (pointConst)S, (pointConst)Q, (bigCurveData*)E);
}
// #####################
// ECC Point Information
// #####################
LIB_EXPORT BOOL ExtEcc_IsPointOnCurve(const Crypt_Point* Q, const Crypt_EccCurve* E)
{
return BnIsPointOnCurve((pointConst)Q, AccessCurveConstants(E));
}
LIB_EXPORT const Crypt_Int* ExtEcc_PointX(const Crypt_Point* point)
{
return (const Crypt_Int*)(((pointConst)point)->x);
}
LIB_EXPORT BOOL ExtEcc_IsInfinityPoint(const Crypt_Point* point)
{
return BnEqualZero(((pointConst)point)->z);
}
// #####################
// ECC Curve Information
// #####################
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetPrime(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGetPrime(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetOrder(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGetOrder(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetCofactor(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGetCofactor(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGet_a(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGet_a(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGet_b(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGet_b(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Point* ExtEcc_CurveGetG(TPM_ECC_CURVE curveId)
{
return (const Crypt_Point*)BnCurveGetG(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetGx(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGetGx(BnGetCurveData(curveId));
}
LIB_EXPORT const Crypt_Int* ExtEcc_CurveGetGy(TPM_ECC_CURVE curveId)
{
return (const Crypt_Int*)BnCurveGetGy(BnGetCurveData(curveId));
}
LIB_EXPORT TPM_ECC_CURVE ExtEcc_CurveGetCurveId(const Crypt_EccCurve* E)
{
return BnCurveGetCurveId(AccessCurveConstants(E));
}

View File

@ -104,12 +104,6 @@
# define DEBUG YES // Default: Either YES or NO
#endif
// This definition is required for the re-factored code
#if (!defined USE_BN_ECC_DATA) || ((USE_BN_ECC_DATA != NO) && (USE_BN_ECC_DATA != YES))
# undef USE_BN_ECC_DATA
# define USE_BN_ECC_DATA YES // Default: Either YES or NO
#endif
////////////////////////////////////////////////////////////////
// DEBUG OPTIONS
////////////////////////////////////////////////////////////////

View File

@ -61,44 +61,47 @@
#include "Tpm.h"
#include "TpmEcc_Signature_ECDAA_fp.h"
#include "TpmEcc_Signature_Util_fp.h"
#include "TpmMath_Debug_fp.h"
#include "TpmMath_Util_fp.h"
#if ALG_ECC && 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 */
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
)
//*** TpmEcc_SignEcdaa()
//
// This function performs 's' = 'r' + 'T' * 'd' mod 'q' where
// 1) 'r' is a random, or pseudo-random value created in the commit phase
// 2) 'nonceK' is a TPM-generated, random value 0 < 'nonceK' < 'n'
// 3) 'T' is mod 'q' of "Hash"('nonceK' || 'digest'), and
// 4) '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.
// Return Type: TPM_RC
// TPM_RC_SCHEME unsupported hash algorithm
// TPM_RC_NO_RESULT cannot get values from random number generator
TPM_RC TpmEcc_SignEcdaa(
TPM2B_ECC_PARAMETER* nonceK, // OUT: 'nonce' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* 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);
TPM_RC retVal;
TPM2B_ECC_PARAMETER r;
HASH_STATE state;
TPM2B_DIGEST T;
CRYPT_INT_MAX(bnT);
//
NOT_REFERENCED(rand);
if(!CryptGenerateR(&r, &scheme->details.ecdaa.count,
if(!CryptGenerateR(&r,
&scheme->details.ecdaa.count,
eccKey->publicArea.parameters.eccDetail.curveID,
&eccKey->name))
retVal = TPM_RC_VALUE;
@ -106,21 +109,22 @@ BnSignEcdaa(
{
// This allocation is here because 'r' doesn't have a value until
// CrypGenerateR() is done.
ECC_INITIALIZED(bnR, &r);
CRYPT_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))
if(!TpmEcc_GenPrivateScalar(bnT, E, E->G, false, rand))
#else // libtpms added end
if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand))
if(!TpmEcc_GenPrivateScalar(bnT, E, rand))
#endif // libtpms added
{
retVal = TPM_RC_NO_RESULT;
break;
}
BnTo2B(bnT, &nonceK->b, 0);
TpmMath_IntTo2B(bnT, &nonceK->b, 0);
T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg);
if(T.t.size == 0)
{
@ -131,11 +135,15 @@ BnSignEcdaa(
CryptDigestUpdate2B(&state, &nonceK->b);
CryptDigestUpdate2B(&state, &digest->b);
CryptHashEnd2B(&state, &T.b);
BnFrom2B(bnT, &T.b);
TpmMath_IntFrom2B(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);
retVal = TpmEcc_SchnorrCalculateS(
bnS,
bnR,
bnT,
bnD,
ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E)));
}
} while(retVal == TPM_RC_NO_RESULT);
// Because the rule is that internal state is not modified if the command

View File

@ -62,18 +62,32 @@
#define _TPMECC_SIGNATURE_ECDAA_FP_H_
#if ALG_ECC && ALG_ECDAA
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
);
//*** TpmEcc_SignEcdaa()
//
// This function performs 's' = 'r' + 'T' * 'd' mod 'q' where
// 1) 'r' is a random, or pseudo-random value created in the commit phase
// 2) 'nonceK' is a TPM-generated, random value 0 < 'nonceK' < 'n'
// 3) 'T' is mod 'q' of "Hash"('nonceK' || 'digest'), and
// 4) '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.
// Return Type: TPM_RC
// TPM_RC_SCHEME unsupported hash algorithm
// TPM_RC_NO_RESULT cannot get values from random number generator
TPM_RC TpmEcc_SignEcdaa(
TPM2B_ECC_PARAMETER* nonceK, // OUT: 'nonce' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* 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
);
#endif // ALG_ECC && ALG_ECDAA
#endif // _TPMECC_SIGNATURE_ECDAA_FP_H_

View File

@ -60,62 +60,63 @@
#include "Tpm.h"
#include "TpmEcc_Signature_ECDSA_fp.h"
#include "TpmToOsslMath_fp.h" // libtpms added
#include "TpmMath_Debug_fp.h"
#include "TpmMath_Util_fp.h"
#include "BnToOsslMath_fp.h"
#if ALG_ECC && ALG_ECDSA
/* 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. */
//*** TpmEcc_AdjustEcdsaDigest()
// 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
)
static Crypt_Int* TpmEcc_AdjustEcdsaDigest(
Crypt_Int* bnD, // OUT: the adjusted digest
const TPM2B_DIGEST* digest, // IN: digest to adjust
const Crypt_Int* max // IN: value that indicates the maximum
// number of bits in the results
)
{
int bitsInMax = BnSizeInBits(max);
int shift;
int bitsInMax = ExtMath_SizeInBits(max);
int shift;
//
if(digest == NULL)
BnSetWord(bnD, 0);
ExtMath_SetWord(bnD, 0);
else
{
BnFromBytes(bnD, digest->t.buffer,
(NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax)));
shift = BnSizeInBits(bnD) - bitsInMax;
ExtMath_IntFromBytes(bnD,
digest->t.buffer,
(NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax)));
shift = ExtMath_SizeInBits(bnD) - bitsInMax;
if(shift > 0)
BnShiftRight(bnD, bnD, shift);
ExtMath_ShiftRight(bnD, bnD, shift);
}
return bnD;
}
#endif // libtpms added
/* 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. */
//*** TpmEcc_SignEcdsa()
// This function implements the ECDSA signing algorithm. The method is described
// in the comments below.
#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
)
TpmEcc_SignEcdsa(Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Int* 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;
CRYPT_ECC_NUM(bnK);
CRYPT_ECC_NUM(bnIk);
CRYPT_INT_VAR(bnE, MAX_ECC_KEY_BITS);
CRYPT_POINT_VAR(ecR);
CRYPT_ECC_NUM(bnX);
const Crypt_Int* order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(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
@ -132,63 +133,68 @@ BnSignEcdsa(
// 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.
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))
if(!TpmEcc_GenerateKeyPair(bnK, ecR, E, rand))
continue;
// get mutable copy of X coordinate
ExtMath_Copy(bnX, ExtEcc_PointX(ecR));
// x coordinate is mod p. Make it mod q
BnMod(ecR->x, order);
ExtMath_Mod(bnX, order);
// Make sure that it is not zero;
if(BnEqualZero(ecR->x))
if(ExtMath_IsZero(bnX))
continue;
// write the modular reduced version of r as part of the signature
BnCopy(bnR, ecR->x);
ExtMath_Copy(bnR, bnX);
// Make sure that a modular inverse exists and try again if not
OK = (BnModInverse(bnIk, bnK, order));
OK = (ExtMath_ModInverse(bnIk, bnK, order));
if(OK)
break;
}
if(!OK)
goto Exit;
EcdsaDigest(bnE, digest, order);
TpmEcc_AdjustEcdsaDigest(bnE, digest, order);
// now have inverse of K (bnIk), e (bnE), r (bnR), d (bnD) and
// CurveGetOrder(E)
// ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E))
// Compute s = k^-1 (e + r*d)(mod q)
// first do s = r*d mod q
BnModMult(bnS, bnR, bnD, order);
ExtMath_ModMult(bnS, bnR, bnD, order);
// s = e + s = e + r * d
BnAdd(bnS, bnE, bnS);
ExtMath_Add(bnS, bnE, bnS);
// s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n)
BnModMult(bnS, bnIk, bnS, order);
ExtMath_ModMult(bnS, bnIk, bnS, order);
// If S is zero, try again
} while(BnEqualZero(bnS));
} while(ExtMath_IsZero(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
)
TpmEcc_SignEcdsa(Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Int* 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();
ECDSA_SIG* sig = NULL;
EC_KEY* eckey;
int retVal;
const BIGNUM* r;
const BIGNUM* s;
BIGNUM* d = BN_new();
d = BigInitialized(d, bnD);
d = BigInitialized(d, (bigConst)bnD);
eckey = EC_KEY_new();
@ -206,8 +212,8 @@ BnSignEcdsa(
ERROR_EXIT(TPM_RC_FAILURE);
ECDSA_SIG_get0(sig, &r, &s);
OsslToTpmBn(bnR, r);
OsslToTpmBn(bnS, s);
OsslToTpmBn((bigNum)bnR, r);
OsslToTpmBn((bigNum)bnS, s);
retVal = TPM_RC_SUCCESS;
@ -220,33 +226,35 @@ BnSignEcdsa(
}
#endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end
/* 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 */
//*** TpmEcc_ValidateSignatureEcdsa()
// 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'
// Return Type: TPM_RC
// 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
)
TpmEcc_ValidateSignatureEcdsa(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
const Crypt_Point* 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;
CRYPT_INT_VAR(bnE, MAX_ECC_KEY_BITS);
CRYPT_POINT_VAR(ecR);
CRYPT_ECC_NUM(bnU1);
CRYPT_ECC_NUM(bnU2);
CRYPT_ECC_NUM(bnW);
CRYPT_ECC_NUM(bnV);
const Crypt_Int* order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E));
TPM_RC retVal = TPM_RC_SIGNATURE;
//
// Get adjusted digest
EcdsaDigest(bnE, digest, order);
TpmEcc_AdjustEcdsaDigest(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
@ -255,47 +263,50 @@ BnValidateSignatureEcdsa(
// 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))
if(!ExtMath_ModInverse(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);
ExtMath_ModMult(bnU1, bnE, bnW, order);
ExtMath_ModMult(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)
if(TpmEcc_PointMult(
ecR, ExtEcc_CurveGetG(ExtEcc_CurveGetCurveId(E)), bnU1, ecQ, bnU2, E)
!= TPM_RC_SUCCESS)
goto Exit;
// 7. Compute v = Rx mod n.
BnMod(ecR->x, order);
ExtMath_Copy(bnV, ExtEcc_PointX(ecR));
ExtMath_Mod(bnV, order);
// 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID
if(BnUnsignedCmp(ecR->x, bnR) != 0)
if(ExtMath_UnsignedCmp(bnV, 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
)
TpmEcc_ValidateSignatureEcdsa(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
const Crypt_Point* 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);
int retVal;
int rc;
ECDSA_SIG* sig = NULL;
EC_KEY* eckey = NULL;
BIGNUM* r = BN_new();
BIGNUM* s = BN_new();
EC_POINT* q = EcPointInitialized((bn_point_t*)ecQ, E);
r = BigInitialized(r, bnR);
s = BigInitialized(s, bnS);
r = BigInitialized(r, (bigConst)bnR);
s = BigInitialized(s, (bigConst)bnS);
sig = ECDSA_SIG_new();
eckey = EC_KEY_new();

View File

@ -62,28 +62,33 @@
#define _TPMECC_SIGNATURE_ECDSA_FP_H_
#if ALG_ECC && ALG_ECDSA
//*** TpmEcc_SignEcdsa()
// This function implements the ECDSA signing algorithm. The method is described
// in the comments below.
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
);
TpmEcc_SignEcdsa(Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Int* bnD, // IN: private signing key
const TPM2B_DIGEST* digest, // IN: the digest to sign
RAND_STATE* rand // IN: used in debug of signing
);
//*** TpmEcc_ValidateSignatureEcdsa()
// 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'
// Return Type: TPM_RC
// TPM_RC_SIGNATURE signature not valid
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
);
TpmEcc_ValidateSignatureEcdsa(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
const Crypt_Point* ecQ, // IN: the public point of the key
const TPM2B_DIGEST* digest // IN: the digest that was signed
);
#endif // ALG_ECC && ALG_ECDSA
#endif // _TPMECC_SIGNATURE_ECDSA_FP_H_

View File

@ -60,65 +60,51 @@
#include "Tpm.h"
#include "TpmEcc_Signature_SM2_fp.h"
#include "TpmMath_Debug_fp.h"
#include "TpmMath_Util_fp.h"
#if ALG_ECC && 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
)
//*** TpmEcc_SignEcSm2()
// 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'). This function signs 'e'.
// Return Type: TPM_RC
// TPM_RC_VALUE bad curve
TPM_RC TpmEcc_SignEcSm2(Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* bnD, // IN: the private key
const TPM2B_DIGEST* digest, // IN: the digest to sign
RAND_STATE* rand // IN: random number generator (mostly for
// debug)
)
{
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 */
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;
CRYPT_INT_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be
CRYPT_ECC_NUM(bnN);
CRYPT_ECC_NUM(bnK);
CRYPT_ECC_NUM(bnT); // temp
CRYPT_POINT_VAR(Q1);
const Crypt_Int* order =
(E != NULL) ? ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E)) : NULL;
// libtpms added begin
UINT32 orderBits = BnSizeInBits(order);
UINT32 orderBits = ExtMath_SizeInBits(order);
BOOL atByteBoundary = (orderBits & 7) == 0;
ECC_NUM(bnK1);
CRYPT_ECC_NUM(bnK1);
// libtpms added end
//
#ifdef _SM2_SIGN_DEBUG
BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1"
"9A87E6FC682D48BB5D42E3D9B9EFFE76");
BnFromHex(bnD, "128B2FA8BD433C6C068C8D803DFF7979"
"2A519A55171B1B650C23661D15897263");
#endif
# ifdef _SM2_SIGN_DEBUG
TpmEccDebug_FromHex(bnE,
"B524F552CD82B8B028476E005C377FB1"
"9A87E6FC682D48BB5D42E3D9B9EFFE76",
MAX_ECC_KEY_BYTES);
TpmEccDebug_FromHex(bnD,
"128B2FA8BD433C6C068C8D803DFF7979"
"2A519A55171B1B650C23661D15897263",
MAX_ECC_KEY_BYTES);
# endif
// A3: Use random number generator to generate random number 1 <= k <= n-1;
// NOTE: Ax: numbers are from the SM2 standard
loop:
@ -134,129 +120,140 @@ BnSignEcSm2(
// 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
BnGenerateRandomInRange((bigNum)bnK, (bigConst)order, rand);
ExtMath_Add(bnK1, bnK, order);
# ifdef _SM2_SIGN_DEBUG
TpmEccDebug_FromHex(bnK,
"6CB28D99385C175C94F94E934817663F"
"C176D925DD72B727260DBAAE1FB2F96F",
MAX_ECC_KEY_BYTES);
# 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))
if(!ExtEcc_PointMultiply(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))
BnGenerateRandomInRangeAllBytes((bigNum)bnK, (bigNum)order, rand);
# ifdef _SM2_SIGN_DEBUG
TpmEccDebug_FromHex(bnK,
"6CB28D99385C175C94F94E934817663F"
"C176D925DD72B727260DBAAE1FB2F96F",
MAX_ECC_KEY_BYTES);
# endif
if(!ExtEcc_PointMultiply(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
// A5: Figure out 'r' = ('e' + 'x1') mod 'n',
ExtMath_Add(bnR, bnE, ExtEcc_PointX(Q1));
ExtMath_Mod(bnR, order);
# ifdef _SM2_SIGN_DEBUG
pAssert(TpmEccDebug_HexEqual(bnR,
"40F1EC59F793D9F49E09DCEF49130D41"
"94F79FB1EED2CAA55BACDB49C4E755D1"));
# endif
// if r=0 or r+k=n, return to A3;
if(BnEqualZero(bnR))
if(ExtMath_IsZero(bnR))
goto loop;
BnAdd(bnT, bnK, bnR);
if(BnUnsignedCmp(bnT, bnN) == 0)
ExtMath_Add(bnT, bnK, bnR);
if(ExtMath_UnsignedCmp(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
ExtMath_AddWord(bnT, bnD, 1);
ExtMath_ModInverse(bnT, bnT, order);
# ifdef _SM2_SIGN_DEBUG
pAssert(TpmEccDebug_HexEqual(bnT,
"79BFCF3052C80DA7B939E0C6914A18CB"
"B2D96D8555256E83122743A7D4F5F956"));
# endif
// compute s = t * (k - r * dA) mod n
BnModMult(bnS, bnR, bnD, order);
ExtMath_ModMult(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))
ExtMath_Subtract(bnS, order, bnS);
ExtMath_Add(bnS, bnK, bnS);
ExtMath_ModMult(bnS, bnS, bnT, order);
# ifdef _SM2_SIGN_DEBUG
pAssert(TpmEccDebug_HexEqual(bnS,
"6FC6DAC32C5D5CF10C77DFB20F7C2EB6"
"67A457872FB09EC56327A67EC7DEEBE7"));
# endif
if(ExtMath_IsZero(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
# ifdef _SM2_SIGN_DEBUG
pAssert(TpmEccDebug_HexEqual(bnR,
"40F1EC59F793D9F49E09DCEF49130D41"
"94F79FB1EED2CAA55BACDB49C4E755D1"));
pAssert(TpmEccDebug_HexEqual(bnS,
"6FC6DAC32C5D5CF10C77DFB20F7C2EB6"
"67A457872FB09EC56327A67EC7DEEBE7"));
# endif
return TPM_RC_SUCCESS;
}
/* 10.2.12.3.8 BnValidateSignatureEcSm2() */
/* This function is used to validate an SM2 signature. */
/* Error Returns Meaning */
/* TPM_RC_SIGNATURE signature not valid */
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
)
//*** TpmEcc_ValidateSignatureEcSm2()
// This function is used to validate an SM2 signature.
// Return Type: TPM_RC
// TPM_RC_SIGNATURE signature not valid
TPM_RC TpmEcc_ValidateSignatureEcSm2(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Point* 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
CRYPT_POINT_VAR(P);
CRYPT_ECC_NUM(bnRp);
CRYPT_ECC_NUM(bnT);
CRYPT_INT_MAX_INITIALIZED(bnE, digest);
BOOL OK;
const Crypt_Int* order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(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
pAssert(TpmEccDebug_HexEqual(bnR,
"40F1EC59F793D9F49E09DCEF49130D41"
"94F79FB1EED2CAA55BACDB49C4E755D1"));
pAssert(TpmEccDebug_HexEqual(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
ExtMath_Add(bnT, bnR, bnS);
ExtMath_Mod(bnT, order);
# ifdef _SM2_SIGN_DEBUG
pAssert(TpmEccDebug_HexEqual(bnT,
"2B75F07ED7ECE7CCC1C8986B991F441A"
"D324D6D619FE06DD63ED32E0C997C801"));
# endif
// c) verify that t > 0
OK = !BnEqualZero(bnT);
OK = !ExtMath_IsZero(bnT);
if(!OK)
// set T to a value that should allow rest of the computations to run
// without trouble
BnCopy(bnT, bnS);
ExtMath_Copy(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
OK = ExtEcc_PointMultiplyAndAdd(P, NULL, bnS, ecQ, bnT, E);
# ifdef _SM2_SIGN_DEBUG
pAssert(OK
&& TpmEccDebug_HexEqual(ExtEcc_PointX(P),
"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);
OK = OK && ExtMath_Add(bnRp, bnE, ExtEcc_PointX(P));
OK = OK && ExtMath_Mod(bnRp, order);
// f) verify that r' = r
OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0);
OK = OK && (ExtMath_UnsignedCmp(bnR, bnRp) == 0);
if(!OK)
return TPM_RC_SIGNATURE;

View File

@ -62,26 +62,34 @@
#define _TPMECC_SIGNATURE_SM2_FP_H_
#if ALG_ECC && ALG_SM2
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)
);
//*** TpmEcc_SignEcSm2()
// 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'). This function signs 'e'.
// Return Type: TPM_RC
// TPM_RC_VALUE bad curve
TPM_RC TpmEcc_SignEcSm2(Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* bnD, // IN: the private key
const TPM2B_DIGEST* digest, // IN: the digest to sign
RAND_STATE* rand // IN: random number generator (mostly for
// debug)
);
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
);
//*** TpmEcc_ValidateSignatureEcSm2()
// This function is used to validate an SM2 signature.
// Return Type: TPM_RC
// TPM_RC_SIGNATURE signature not valid
TPM_RC TpmEcc_ValidateSignatureEcSm2(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Point* ecQ, // IN: the public point of the key
const TPM2B_DIGEST* digest // IN: the digest that was signed
);
#endif // ALG_ECC && ALG_SM2
#endif // _TPMECC_SIGNATURE_SM2_FP_H_

View File

@ -61,80 +61,84 @@
#include "Tpm.h"
#include "TpmEcc_Signature_Schnorr_fp.h"
#include "TpmEcc_Signature_Util_fp.h"
#include "TpmMath_Debug_fp.h"
#include "TpmMath_Util_fp.h"
#if ALG_ECC && 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
)
//*** SchnorrReduce()
// Function to reduce a hash result if it's magnitude is too large. The size of
// 'number' is set so that it has no more bytes of significance than 'reference'
// value. If the resulting number can have more bits of significance than
// 'reference'.
static void SchnorrReduce(TPM2B* number, // IN/OUT: Value to reduce
const Crypt_Int* reference // IN: the reference value
)
{
UINT16 maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference));
UINT16 maxBytes = (UINT16)BITS_TO_BYTES(ExtMath_SizeInBits(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 */
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
)
//*** 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'
//
// Return Type: TPM_RC
// TPM_RC_NO_RESULT failure in the Schnorr sign process
// TPM_RC_SCHEME hashAlg can't produce zero-length digest
TPM_RC TpmEcc_SignEcSchnorr(
Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* 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);
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);
TPM2B_T T2b;
TPM2B* e = &T2b.b;
TPM_RC retVal = TPM_RC_NO_RESULT;
const Crypt_Int* order;
const Crypt_Int* prime;
CRYPT_ECC_NUM(bnK);
CRYPT_POINT_VAR(ecR);
//
// Parameter checks
if(E == NULL)
ERROR_EXIT(TPM_RC_VALUE);
C = AccessCurveData(E);
order = CurveGetOrder(C);
prime = CurveGetOrder(C);
order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E));
prime = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E));
// 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);
ExtMath_SetWord(bnR, 0);
ExtMath_SetWord(bnS, 0);
ERROR_EXIT(TPM_RC_SCHEME);
}
do
{
// Generate a random key pair
if(!BnEccGenerateKeyPair(bnK, ecR, E, rand))
if(!TpmEcc_GenerateKeyPair(bnK, ecR, E, rand))
break;
// Convert R.x to a string
BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime)));
TpmMath_IntTo2B(ExtEcc_PointX(ecR),
e,
(NUMBYTES)BITS_TO_BYTES(ExtMath_SizeInBits(prime)));
// f) compute r = Hash(e || P) (mod n)
CryptHashStart(&hashState, hashAlg);
CryptDigestUpdate2B(&hashState, e);
@ -143,52 +147,55 @@ BnSignEcSchnorr(
// Reduce the hash size if it is larger than the curve order
SchnorrReduce(e, order);
// Convert hash to number
BnFrom2B(bnR, e);
TpmMath_IntFrom2B(bnR, e);
// libtpms: Note: e is NOT a concern for constant-timeness
// Do the Schnorr computation
retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C));
retVal = TpmEcc_SchnorrCalculateS(
bnS, bnK, bnR, bnD, ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E)));
} while(retVal == TPM_RC_NO_RESULT);
Exit:
return retVal;
}
/* 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 */
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
)
//*** TpmEcc_ValidateSignatureEcSchnorr()
// This function is used to validate an EC Schnorr signature.
// Return Type: TPM_RC
// TPM_RC_SIGNATURE signature not valid
TPM_RC TpmEcc_ValidateSignatureEcSchnorr(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Point* 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;
CRYPT_INT_MAX(bnRn);
CRYPT_POINT_VAR(ecE);
CRYPT_INT_MAX(bnEx);
const Crypt_Int* order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E));
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;
TPM2B_BUFFER Ex2 = {{sizeof(Ex2.t.buffer), {0}}};
BOOL OK;
//
// E = [s]G - [r]Q
BnMod(bnR, order);
ExtMath_Mod(bnR, order);
// Make -r = n - r
BnSub(bnRn, order, bnR);
ExtMath_Subtract(bnRn, order, bnR);
// E = [s]G + [-r]Q
OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS;
OK = TpmEcc_PointMult(
ecE, ExtEcc_CurveGetG(ExtEcc_CurveGetCurveId(E)), bnS, ecQ, bnRn, E)
== TPM_RC_SUCCESS;
// // reduce the x portion of E mod q
// OK = OK && BnMod(ecE->x, order);
// OK = OK && ExtMath_Mod(ecE->x, order);
// Convert to byte string
OK = OK && BnTo2B(ecE->x, &Ex2.b,
(NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order))));
OK = OK
&& TpmMath_IntTo2B(ExtEcc_PointX(ecE),
&Ex2.b,
(NUMBYTES)(BITS_TO_BYTES(ExtMath_SizeInBits(order))));
if(OK)
{
// Ex = h(pE.x || digest)
@ -197,9 +204,9 @@ BnValidateSignatureEcSchnorr(
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);
TpmMath_IntFrom2B(bnEx, &Ex2.b);
// see if Ex matches R
OK = BnUnsignedCmp(bnEx, bnR) == 0;
OK = ExtMath_UnsignedCmp(bnEx, bnR) == 0;
}
return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE;
}

View File

@ -62,28 +62,29 @@
#define _TPMECC_SIGNATURE_SCHNORR_FP_H_
#if ALG_ECC && ALG_ECSCHNORR
TPM_RC TpmEcc_SignEcSchnorr(
Crypt_Int* bnR, // OUT: 'r' component of the signature
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_EccCurve* E, // IN: the curve used in signing
Crypt_Int* 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
);
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
);
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
);
//*** TpmEcc_ValidateSignatureEcSchnorr()
// This function is used to validate an EC Schnorr signature.
// Return Type: TPM_RC
// TPM_RC_SIGNATURE signature not valid
TPM_RC TpmEcc_ValidateSignatureEcSchnorr(
Crypt_Int* bnR, // IN: 'r' component of the signature
Crypt_Int* bnS, // IN: 's' component of the signature
TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature
const Crypt_EccCurve* E, // IN: the curve used in the signature
// process
Crypt_Point* ecQ, // IN: the public point of the key
const TPM2B_DIGEST* digest // IN: the digest that was signed
);
#endif // ALG_ECC && ALG_ECSCHNORR
#endif // _TPMECC_SIGNATURE_SCHNORR_FP_H_

View File

@ -61,45 +61,47 @@
// functions shared by multiple signature algorithms
#include "Tpm.h"
#include "TpmEcc_Signature_Util_fp.h"
#include "TpmMath_Debug_fp.h"
#include "TpmMath_Util_fp.h"
#if(ALG_ECC && (ALG_ECSCHNORR || ALG_ECDAA))
/* 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 */
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
)
//*** TpmEcc_SchnorrCalculateS()
// This contains the Schnorr signature (S) computation. It is used by both ECDAA and
// Schnorr signing. The result is computed as: ['s' = 'k' + 'r' * 'd' (mod 'n')]
// where
// 1) 's' is the signature
// 2) 'k' is a random value
// 3) 'r' is the value to sign
// 4) 'd' is the private EC key
// 5) 'n' is the order of the curve
// Return Type: TPM_RC
// TPM_RC_NO_RESULT the result of the operation was zero or 'r' (mod 'n')
// is zero
TPM_RC TpmEcc_SchnorrCalculateS(
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_Int* bnK, // IN: a random value
Crypt_Int* bnR, // IN: the signature 'r' value
const Crypt_Int* bnD, // IN: the private key
const Crypt_Int* 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);
CRYPT_INT_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8);
//
// Reduce bnR without changing the input value
BnDiv(NULL, bnT1, bnR, bnN);
if(BnEqualZero(bnT1))
ExtMath_Divide(NULL, bnT1, bnR, bnN);
if(ExtMath_IsZero(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);
ExtMath_Multiply(bnT1, bnT1, bnD);
// k + r * d
ExtMath_Add(bnT1, bnT1, bnK);
// k + r * d (mod n)
BnDiv(NULL, bnS, bnT1, bnN);
return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS;
ExtMath_Divide(NULL, bnS, bnT1, bnN);
return (ExtMath_IsZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS;
}
#endif // (ALG_ECC && (ALG_ECSCHNORR || ALG_ECDAA))

View File

@ -63,15 +63,25 @@
#define _TPMECC_SIGNATURE_UTIL_FP_H_
#if ALG_ECC
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
);
//*** TpmEcc_SchnorrCalculateS()
// This contains the Schnorr signature (S) computation. It is used by both ECDSA and
// Schnorr signing. The result is computed as: ['s' = 'k' + 'r' * 'd' (mod 'n')]
// where
// 1) 's' is the signature
// 2) 'k' is a random value
// 3) 'r' is the value to sign
// 4) 'd' is the private EC key
// 5) 'n' is the order of the curve
// Return Type: TPM_RC
// TPM_RC_NO_RESULT the result of the operation was zero or 'r' (mod 'n')
// is zero
TPM_RC TpmEcc_SchnorrCalculateS(
Crypt_Int* bnS, // OUT: 's' component of the signature
const Crypt_Int* bnK, // IN: a random value
Crypt_Int* bnR, // IN: the signature 'r' value
const Crypt_Int* bnD, // IN: the private key
const Crypt_Int* bnN // IN: the order of the curve
);
#endif // ALG_ECC
#endif // _TPMECC_SIGNATURE_UTIL_FP_H_

123
src/tpm2/TpmEcc_Util.c Normal file
View File

@ -0,0 +1,123 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
//** Introduction
// This file contains utility functions to help using the external Math library
// for Ecc functions.
#include "Tpm.h"
#include "TpmMath_Util_fp.h"
#include "TpmEcc_Util_fp.h"
#if ALG_ECC
//***
// TpmEcc_PointFrom2B() Function to create a Crypt_Point structure from a 2B
// point. The target point is expected to have memory allocated and
// uninitialized. A TPMS_ECC_POINT is going to be two ECC values in the same
// buffer. The values are going to be the size of the modulus. They are in
// modular form.
//
// NOTE: This function considers both parameters optional because of use
// cases where points may not be specified in the calling function. If the
// initializer or point buffer is NULL, then NULL is returned. As a result, the
// only error detection when the initializer value is invalid is to return NULL
// in that error case as well. If a caller wants to handle that error case
// differently, then the caller must perform the correct validation before/after
// this function.
LIB_EXPORT Crypt_Point* TpmEcc_PointFrom2B(
Crypt_Point* ecP, // OUT: the preallocated point structure
TPMS_ECC_POINT* p // IN: the number to convert
)
{
if(p == NULL)
return NULL;
if(ecP != NULL)
{
return ExtEcc_PointFromBytes(
ecP, p->x.t.buffer, p->x.t.size, p->y.t.buffer, p->y.t.size);
}
return ecP; // will return NULL if ecP is NULL.
}
//*** TpmEcc_PointTo2B()
// This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT
// contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters
// is dependent on the maximum EC key size used in an implementation.
// The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B
// values, each as large as a MAX_ECC_PARAMETER_BYTES
LIB_EXPORT BOOL TpmEcc_PointTo2B(
TPMS_ECC_POINT* p, // OUT: the converted 2B structure
const Crypt_Point* ecP, // IN: the values to be converted
const Crypt_EccCurve* E // IN: curve descriptor for the point
)
{
pAssert(p && ecP && E);
TPM_ECC_CURVE curveId = ExtEcc_CurveGetCurveId(E);
NUMBYTES size = CryptEccGetKeySizeForCurve(curveId);
size = (UINT16)BITS_TO_BYTES(size);
MemorySet(p, 0, sizeof(*p));
p->x.t.size = size;
p->y.t.size = size;
return ExtEcc_PointToBytes(
ecP, p->x.t.buffer, &p->x.t.size, p->y.t.buffer, &p->y.t.size);
}
#endif // ALG_ECC

89
src/tpm2/TpmEcc_Util_fp.h Normal file
View File

@ -0,0 +1,89 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
#ifndef _TPMECC_UTIL_FP_H_
#define _TPMECC_UTIL_FP_H_
#if ALG_ECC
//*** TpmEcc_PointFrom2B()
// Function to create a Crypt_Point structure from a 2B point.
// This function doesn't take an Crypt_EccCurve for legacy reasons -
// this should probably be changed.
// returns NULL if the input value is invalid or doesn't fit.
LIB_EXPORT Crypt_Point* TpmEcc_PointFrom2B(
Crypt_Point* ecP, // OUT: the preallocated point structure
TPMS_ECC_POINT* p // IN: the number to convert
);
//*** TpmEcc_PointTo2B()
// This function converts a Crypt_Point into a TPMS_ECC_POINT. A TPMS_ECC_POINT
// contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters
// is dependent on the maximum EC key size used in an implementation.
// The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B
// values, each as large as a MAX_ECC_PARAMETER_BYTES
LIB_EXPORT BOOL TpmEcc_PointTo2B(
TPMS_ECC_POINT* p, // OUT: the converted 2B structure
const Crypt_Point* ecP, // IN: the values to be converted
const Crypt_EccCurve* E // IN: curve descriptor for the point
);
#endif // ALG_ECC
#endif // _TPMECC_UTIL_FP_H_

170
src/tpm2/TpmMath_Debug.c Normal file
View File

@ -0,0 +1,170 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
//** Introduction
// This file contains debug utility functions to help testing Ecc.
#include "Tpm.h"
#include "TpmEcc_Util_fp.h"
#include "TpmMath_Debug_fp.h"
#if ALG_SM2
# ifdef _SM2_SIGN_DEBUG
//*** SafeGetStringLength()
// self-implemented version of strnlen_s. This is necessary because
// some environments don't have a C-runtime library, or are limited to
// C99, and strnlen_s was standardized in C11.
static size_t SafeGetStringLength(const char* string, size_t maxsize)
{
// strnlen_s has two boundary conditions:
// return 0 if pointer is nullptr, or
// maxsize if no null character is found.
if(string == NULL)
return 0;
const char* pos = string;
size_t size = 0;
while(*pos != '\0' && size < maxsize)
{
pos++;
size++;
}
return size;
}
// convert from hex value. If invalid, result will be out of range.
static LIB_EXPORT BYTE FromHex(unsigned char c)
{
// hack for the ASCII characters we care about
BYTE upper = (c & (~0x20));
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'A' && c <= 'F')
return c - 'A';
return 255;
}
//*** TpmEccDebug_FromHex()
// Convert a hex string into a Crypt_Int*. This is primarily used in debugging.
LIB_EXPORT Crypt_Int* TpmEccDebug_FromHex(
Crypt_Int* bn, // OUT:
const unsigned char* hex, // IN:
size_t maxsizeHex // IN: maximum size of hex
)
{
// if value is larger than this, then fail
BYTE tempBuf[MAX_ECC_KEY_BYTES];
MemorySet(tempBuf, 0, sizeof(tempBuf));
ExtMath_SetWord(bn, 0);
size_t len = SafeGetStringLength(hex, maxsizeHex);
BOOL OK = FALSE;
if((len % 2) == 0)
{
OK = TRUE;
for(size_t i = 0; i < len; i += 2)
{
BYTE highNibble = FromHex(*hex);
hex++;
BYTE lowNibble = FromHex(*hex);
hex++;
// unsigned, no need to check zero
if(highNibble > 15 || lowNibble > 15)
{
OK = FALSE;
break;
}
BYTE b = ((highNibble << 4) | lowNibble);
tempBuf[i / 2] = b;
}
if(OK)
{
ExtMath_IntFromBytes(bn, tempBuf, (NUMBYTES)(len / 2));
}
}
if(!OK)
{
// this should only be called in testing, so any
// errors are fatal.
FAIL(FATAL_ERROR_INTERNAL);
}
return bn;
}
//*** TpmEccDebug_HexEqual()
// This function compares a bignum value to a hex string.
// using TpmEcc namespace because code assumes the max size
// is correct for ECC.
// Return Type: BOOL
// TRUE(1) values equal
// FALSE(0) values not equal
BOOL TpmEccDebug_HexEqual(const Crypt_Int* bn, //IN: big number value
const char* c //IN: character string number
)
{
CRYPT_ECC_NUM(bnC);
TpmEccDebug_FromHex(bnC, c, MAX_ECC_KEY_BYTES * 2 + 1);
return (ExtMath_UnsignedCmp(bn, bnC) == 0);
}
# endif // _SM2_SIGN_DEBUG
#endif // ALG_SM2

View File

@ -0,0 +1,86 @@
/********************************************************************************/
/* */
/* */
/* Written by Ken Goldman */
/* 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, 2023 */
/* */
/********************************************************************************/
//
// debug and test utilities. Not expected to be compiled into final products
#ifndef _TPMMATH_DEBUG_FP_H_
#define _TPMMATH_DEBUG_FP_H_
#if ALG_ECC || ALG_RSA
//*** TpmEccDebug_HexEqual()
// This function compares a bignum value to a hex string.
// using TpmEcc namespace because code assumes the max size
// is correct for ECC.
// Return Type: BOOL
// TRUE(1) values equal
// FALSE(0) values not equal
BOOL TpmMath_Debug_HexEqual(const Crypt_Int* bn, //IN: big number value
const char* c //IN: character string number
);
LIB_EXPORT Crypt_Int* TpmMath_Debug_FromHex(
Crypt_Int* bn, // OUT:
const unsigned char* hex, // IN:
size_t maxsizeHex // IN: maximum size of hex
);
#endif // ALG_ECC or ALG_RSA
#endif //_TPMMATH_DEBUG_FP_H_

View File

@ -97,35 +97,24 @@
//** 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;
#define ECC_BITS (MAX_ECC_KEY_BYTES * 8)
CRYPT_INT_TYPE(ecc, ECC_BITS);
#define CRYPT_ECC_NUM(name) CRYPT_INT_VAR(name, ECC_BITS)
#define CRYPT_ECC_INITIALIZED(name, initializer) \
CRYPT_INT_INITIALIZED(name, ECC_BITS, initializer)
typedef struct TPM_ECC_CURVE_METADATA
{
const TPM_ECC_CURVE curveId;
const UINT16 keySizeBits;
const TPMT_KDF_SCHEME kdf;
const TPMT_ECC_SCHEME sign;
const BYTE* OID;
} TPM_ECC_CURVE_METADATA;
//*** Macros
#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)
extern const TPM_ECC_CURVE_METADATA eccCurves[ECC_CURVE_COUNT];
#endif

View File

@ -69,7 +69,9 @@
#if ALG_ECC
//** Functions
# if SIMULATION
void EccSimulationEnd(void);
# endif // SIMULATION
//*** CryptEccInit()
// This function is called at _TPM_Init
@ -92,7 +94,7 @@ void ClearPoint2B(TPMS_ECC_POINT* p // IN: the point
// Return Type: const TPM_ECC_CURVE_METADATA
// NULL curve with the indicated TPM_ECC_CURVE is not implemented
// != NULL pointer to the curve data
LIB_EXPORT const ECC_CURVE* CryptEccGetParametersByCurveId(
LIB_EXPORT const TPM_ECC_CURVE_METADATA* CryptEccGetParametersByCurveId(
TPM_ECC_CURVE curveId // IN: the curveID
);
@ -101,11 +103,6 @@ LIB_EXPORT const ECC_CURVE* CryptEccGetParametersByCurveId(
LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve(TPM_ECC_CURVE curveId // IN: the curve
);
const ECC_CURVE_DATA *
GetCurveData(
TPM_ECC_CURVE curveId // IN: the curveID
);
//***CryptEccGetOID()
const BYTE* CryptEccGetOID(TPM_ECC_CURVE curveId);
@ -115,13 +112,6 @@ const BYTE* CryptEccGetOID(TPM_ECC_CURVE curveId);
// than or equal to the number of implemented curves, TPM_ECC_NONE is returned.
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
);
//*** CryptCapGetECCCurve()
// This function returns the list of implemented ECC curves.
// Return Type: TPMI_YES_NO
@ -181,62 +171,75 @@ BOOL CryptEccGetParameters(
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
);
//*** TpmEcc_IsValidPrivateEcc()
// Checks that 0 < 'x' < 'q'
BOOL TpmEcc_IsValidPrivateEcc(const Crypt_Int* x, // IN: private key to check
const Crypt_EccCurve* E // IN: the curve to check
);
LIB_EXPORT BOOL CryptEccIsValidPrivateKey(TPM2B_ECC_PARAMETER* d,
TPM_ECC_CURVE curveId);
//*** TpmEcc_PointMult()
// This function does a point multiply of the form 'R' = ['d']'S' + ['u']'Q' where the
// parameters are Crypt_Int* 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.
// Return Type: TPM_RC
// 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
);
TpmEcc_PointMult(Crypt_Point* R, // OUT: computed point
const Crypt_Point* S, // IN: optional point to multiply by 'd'
const Crypt_Int* d, // IN: scalar for [d]S or [d]G
const Crypt_Point* Q, // IN: optional second point
const Crypt_Int* u, // IN: optional second scalar
const Crypt_EccCurve* 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
);
//***TpmEcc_GenPrivateScalar()
// 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 Bits"".
// Return Type: BOOL
// TRUE(1) success
// FALSE(0) failure generating private key
#if !USE_OPENSSL_FUNCTIONS_EC // libtpms: added
BOOL TpmEcc_GenPrivateScalar(
Crypt_Int* dOut, // OUT: the qualified random value
const Crypt_EccCurve* E, // IN: curve for which the private key
// needs to be appropriate
RAND_STATE* rand // IN: state for DRBG
);
#else // libtpms: added begin
BOOL TpmEcc_GenPrivateScalar(
Crypt_Int* dOut, // OUT: the qualified random value
const Crypt_EccCurve* E, // IN: curve for which the private key
// needs to be appropriate
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
RAND_STATE* rand // IN: state for DRBG
);
#endif // libtpms: added end
//*** TpmEcc_GenerateKeyPair()
// This function gets a private scalar from the source of random bits and does
// the point multiply to get the public key.
BOOL TpmEcc_GenerateKeyPair(Crypt_Int* bnD, // OUT: private scalar
Crypt_Point* ecQ, // OUT: public point
const Crypt_EccCurve* E, // IN: curve for the point
RAND_STATE* rand // IN: DRBG state to use
);
//***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
@ -320,12 +323,12 @@ LIB_EXPORT TPM_RC CryptEccGenerateKey(
// RNG state
);
// libtpms added begin
// libtpms: added begin
LIB_EXPORT BOOL
CryptEccIsCurveRuntimeUsable(
TPMI_ECC_CURVE curveId
);
// libtpms added end
// libtpms: added end
#endif // ALG_ECC

View File

@ -86,6 +86,7 @@ LIB_EXPORT TPM_RC CryptEccSign(TPMT_SIGNATURE* signature, // OUT: signature
const TPM2B_DIGEST* digest, // IN: digest to sign
TPMT_ECC_SCHEME* scheme, // IN: signing scheme
RAND_STATE* rand);
//*** CryptEccValidateSignature()
// This function validates an EcDsa or EcSchnorr signature.
// The point 'Qin' needs to have been validated to be on the curve of 'curveId'.

View File

@ -80,12 +80,6 @@ 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:
);
//*** BnToBytes()
// This function converts a BIG_NUM to a byte array. It converts the bigNum to a
// big-endian byte string and sets 'size' to the normalized value. If 'size' is an
@ -114,19 +108,31 @@ LIB_EXPORT BOOL BnTo2B(bigConst bn, // IN:
TPM2B* a2B, // OUT:
NUMBYTES size // IN: the desired size
);
#if ALG_ECC
//*** BnPointFromBytes()
// Function to create a BIG_POINT structure from a byte buffer in big-endian order.
// A point is going to be two ECC values in the same buffer. The values are going
// to be the size of the modulus. They are in modular form.
LIB_EXPORT bn_point_t* BnPointFromBytes(
bigPoint ecP, // OUT: the preallocated point structure
const BYTE* x,
NUMBYTES nBytesX,
const BYTE* y,
NUMBYTES nBytesY);
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
);
//*** BnPointToBytes()
// This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT
// contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters
// is dependent on the maximum EC key size used in an implementation.
// The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B
// values, each as large as a MAX_ECC_PARAMETER_BYTES
LIB_EXPORT BOOL BnPointToBytes(
pointConst ecP, // OUT: the preallocated point structure
BYTE* x,
NUMBYTES* pBytesX,
BYTE* y,
NUMBYTES* pBytesY);
#endif // ALG_ECC
#endif // _BN_CONVERT_FP_H_

View File

@ -159,4 +159,13 @@ LIB_EXPORT BOOL BnMaskBits(bigNum bn, // IN/OUT: number to mask
// This function always returns TRUE.
LIB_EXPORT BOOL BnShiftRight(bigNum result, bigConst toShift, uint32_t shiftAmount);
#endif
//*** BnGetCurveData()
// This function returns the pointer for the parameter data
// associated with a curve.
const TPMBN_ECC_CURVE_CONSTANTS* BnGetCurveData(TPM_ECC_CURVE curveId);
//*** BnIsPointOnCurve()
// This function checks if a point is on the curve.
BOOL BnIsPointOnCurve(pointConst Q, const TPMBN_ECC_CURVE_CONSTANTS* C);
#endif // _BN_MATH_FP_H_

View File

@ -84,7 +84,7 @@
//#include "BnOssl.h"
#ifdef MATH_LIB_OSSL
# include "TpmToOsslMath_fp.h"
# include "BnToOsslMath_fp.h"
//** Functions
@ -444,7 +444,7 @@ LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus)
// FALSE(0) failure in operation
static BOOL PointFromOssl(bigPoint pOut, // OUT: resulting point
EC_POINT* pIn, // IN: the point to return
const bigCurve E // IN: the curve
const bigCurveData* E // IN: the curve
)
{
BIGNUM* x = NULL;
@ -478,7 +478,7 @@ static BOOL PointFromOssl(bigPoint pOut, // OUT: resulting point
//*** EcPointInitialized()
// Allocate and initialize a point.
LIB_EXPORT EC_POINT* EcPointInitialized(pointConst initializer, bigCurve E) // libtpms: exported function
LIB_EXPORT EC_POINT* EcPointInitialized(pointConst initializer, const bigCurveData* E) // libtpms: exported function
{
EC_POINT* P = NULL;
@ -510,13 +510,12 @@ LIB_EXPORT EC_POINT* EcPointInitialized(pointConst initializer, bigCurve E) //
// NULL the TPM_ECC_CURVE is not valid or there was a problem in
// in initializing the curve data
// non-NULL points to 'E'
LIB_EXPORT bigCurve
BnCurveInitialize(
bigCurve E, // IN: curve structure to initialize
TPM_ECC_CURVE curveId // IN: curve identifier
)
LIB_EXPORT bigCurveData* BnCurveInitialize(
bigCurveData* E, // IN: curve structure to initialize
TPM_ECC_CURVE curveId // IN: curve identifier
)
{
const ECC_CURVE_DATA *C = GetCurveData(curveId);
const TPMBN_ECC_CURVE_CONSTANTS* C = BnGetCurveData(curveId);
if(C == NULL)
E = NULL;
if(E != NULL)
@ -580,7 +579,7 @@ BnCurveInitialize(
//*** 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)
LIB_EXPORT void BnCurveFree(bigCurveData* E)
{
if(E)
{
@ -597,7 +596,7 @@ LIB_EXPORT void BnCurveFree(bigCurve E)
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
const bigCurve E)
const bigCurveData* E)
{
EC_POINT* pR = EC_POINT_new(E->G);
EC_POINT* pS = EcPointInitialized(S, E);
@ -624,7 +623,7 @@ LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point
bigConst d, // IN: scalar for [d]S or [d]G
pointConst Q, // IN: second point
bigConst u, // IN: second scalar
const bigCurve E // IN: curve
const bigCurveData* E // IN: curve
)
{
EC_POINT* pR = EC_POINT_new(E->G);
@ -633,7 +632,7 @@ LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point
EC_POINT* pQ = EcPointInitialized(Q, E);
BIG_INITIALIZED(bnU, u);
if(S == NULL || S == (pointConst) & (AccessCurveData(E)->base))
if(S == NULL || S == (pointConst) & (AccessCurveConstants(E)->base))
EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX);
else
{
@ -678,7 +677,7 @@ LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point
LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point
pointConst S, // IN: first point to add
pointConst Q, // IN: second point
const bigCurve E // IN: curve
const bigCurveData* E // IN: curve
)
{
EC_POINT* pR = EC_POINT_new(E->G);

View File

@ -67,6 +67,7 @@
#define MATH_LIB_OSSL
#include "BnValues.h"
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
@ -125,15 +126,20 @@ struct bignum_st
typedef struct
{
const ECC_CURVE_DATA* C; // the TPM curve values
const TPMBN_ECC_CURVE_CONSTANTS* 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;
// Define the curve data type expected by the TpmBigNum library:
typedef OSSL_CURVE_DATA *bigCurve;
#define AccessCurveData(E) ((E)->C)
typedef OSSL_CURVE_DATA bigCurveData;
TPM_INLINE const TPMBN_ECC_CURVE_CONSTANTS* AccessCurveConstants(
const bigCurveData* E)
{
return E->C;
}
#include "TpmToOsslSupport_fp.h"
@ -141,12 +147,6 @@ typedef OSSL_CURVE_DATA *bigCurve;
#define OSSL_ENTER() BN_CTX* CTX = OsslContextEnter()
#define OSSL_LEAVE() OsslContextLeave(CTX)
#define CURVE_INITIALIZED(name, initializer) \
OSSL_CURVE_DATA _##name; \
bigCurve name = BnCurveInitialize(&_##name, initializer)
#define CURVE_FREE(name) BnCurveFree(name)
#if 0 /* kgold not used */
// Start and end a local stack frame within the context of the curve frame
#define ECC_ENTER() BN_CTX* CTX = OsslPushContext(E->CTX)

View File

@ -1,9 +1,8 @@
/********************************************************************************/
/* */
/* 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 */
/* */
@ -55,98 +54,41 @@
/* arising in any way out of use or reliance upon this specification or any */
/* information herein. */
/* */
/* (c) Copyright IBM Corp. and others, 2016 - 2019 */
/* (c) Copyright IBM Corp. and others, 2023 */
/* */
/********************************************************************************/
#ifndef TPMTOOSSLMATH_FP_H
#define TPMTOOSSLMATH_FP_H
/*(Auto-generated)
* Created by TpmPrototypes; Version 3.0 July 18, 2017
* Date: Oct 24, 2019 Time: 11:37:07AM
*/
#include <openssl/bn.h>
#ifndef _BN_TO_OSSL_MATH_FP_H_
#define _BN_TO_OSSL_MATH_FP_H_
#ifdef MATH_LIB_OSSL
//*** 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 Type: BOOL
// TRUE(1) success
// FALSE(0) failure because value will not fit or OpenSSL variable doesn't
// exist
BOOL OsslToTpmBn(bigNum bn, const BIGNUM* osslBn);
//*** 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);
#endif // MATHLIB OSSL
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
);
EC_POINT *EcPointInitialized(pointConst initializer,
const bigCurveData* 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
#endif // _TPM_TO_OSSL_MATH_FP_H_

View File

@ -217,32 +217,22 @@ typedef struct constant_point_t
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 (name##_x, bits) name##_x = \
{BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \
BN_STRUCT (name##_y, bits ) name##_y = \
{BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \
BN_STRUCT (name##_z, 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 */
// coords points into x,y,z
// a bigPoint is a pointer to one of these structures, and
// therefore a pointer to bn_point_t (a coords).
// so bigPoint->coords->x->size is the size of x, and
// all 3 components are the same size.
#define BN_POINT_BUF(typename, bits) \
struct bnpt_st_##typename##_t \
{ \
bn_point_t coords; \
BN_STRUCT(typename##_x, MAX_ECC_KEY_BITS) x; \
BN_STRUCT(typename##_y, MAX_ECC_KEY_BITS) y; \
BN_STRUCT(typename##_z, MAX_ECC_KEY_BITS) z; \
}
typedef BN_POINT_BUF(fullpoint, MAX_ECC_KEY_BITS) bn_fullpoint_t;
// TPMBN_ECC_CURVE_CONSTANTS
// =========================
@ -278,13 +268,14 @@ BN_TYPE(ecc, ECC_BITS);
// TPMS_ALGORITHM_DETAIL_ECC
typedef struct
{
TPM_ECC_CURVE curveId; // TPM Algorithm ID for this data
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;
} TPMBN_ECC_CURVE_CONSTANTS;
// Access macros for the TPMBN_ECC_CURVE_CONSTANTS structure. The parameter 'C' is a pointer
// to an TPMBN_ECC_CURVE_CONSTANTS structure. In some libraries, the curve structure E contains
@ -293,14 +284,42 @@ typedef struct
// to the TPMBN_ECC_CURVE_CONSTANTS for access. In some cases, the function does nothing.
// AccessCurveConstants and these functions are all defined as inline so they can be optimized
// away in cases where they are no-ops.
#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)
TPM_INLINE bigConst BnCurveGetPrime(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->prime;
}
TPM_INLINE bigConst BnCurveGetOrder(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->order;
}
TPM_INLINE bigConst BnCurveGetCofactor(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->h;
}
TPM_INLINE bigConst BnCurveGet_a(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->a;
}
TPM_INLINE bigConst BnCurveGet_b(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->b;
}
TPM_INLINE pointConst BnCurveGetG(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return (pointConst) & (C->base);
}
TPM_INLINE bigConst BnCurveGetGx(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->base.x;
}
TPM_INLINE bigConst BnCurveGetGy(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->base.y;
}
TPM_INLINE TPM_ECC_CURVE BnCurveGetCurveId(const TPMBN_ECC_CURVE_CONSTANTS* C)
{
return C->curveId;
}
// Convert bytes in initializers
// This is used for CryptEccData.c.

View File

@ -60,6 +60,8 @@
//** Includes and Defines
#include "Tpm.h"
#include "TpmMath_Util_fp.h"
#include "TpmEcc_Util_fp.h"
#if CC_ECC_Encrypt || CC_ECC_Encrypt
@ -108,11 +110,11 @@ LIB_EXPORT TPM_RC CryptEccEncrypt(
// and plainText
)
{
CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
POINT_INITIALIZED(PB, &key->publicArea.unique.ecc);
POINT_VAR(Px, MAX_ECC_KEY_BITS);
TPMS_ECC_POINT p2;
ECC_NUM(D);
CRYPT_CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
CRYPT_POINT_INITIALIZED(PB, &key->publicArea.unique.ecc);
CRYPT_POINT_VAR(Px);
TPMS_ECC_POINT p2;
CRYPT_ECC_NUM(D);
TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
TPM2B_2ECC z;
int i;
@ -137,12 +139,12 @@ LIB_EXPORT TPM_RC CryptEccEncrypt(
if(TPM_ALG_KDF2 != scheme->scheme)
ERROR_EXIT(TPM_RC_SCHEME);
// generate an ephemeral key from a random k
if (!BnEccGenerateKeyPair(D, Px, E, RANDOM)
// C1 is the public part of the ephemeral key
|| !BnPointTo2B(c1, Px, E)
// Compute P2
|| (BnPointMult(Px, PB, D, NULL, NULL, E) != TPM_RC_SUCCESS)
|| !BnPointTo2B(&p2, Px, E))
if(!TpmEcc_GenerateKeyPair(D, Px, E, RANDOM)
// C1 is the public part of the ephemeral key
|| !TpmEcc_PointTo2B(c1, Px, E)
// Compute P2
|| (TpmEcc_PointMult(Px, PB, D, NULL, NULL, E) != TPM_RC_SUCCESS)
|| !TpmEcc_PointTo2B(&p2, Px, E))
ERROR_EXIT(TPM_RC_NO_RESULT);
//Compute the C3 value hash(x2 || M || y2)
@ -166,7 +168,7 @@ LIB_EXPORT TPM_RC CryptEccEncrypt(
for(i = 0; i < plainText->t.size; i++)
c2->t.buffer[i] ^= plainText->t.buffer[i];
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -188,10 +190,10 @@ LIB_EXPORT TPM_RC CryptEccDecrypt(
// and plainText
)
{
CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
ECC_INITIALIZED(D, &key->sensitive.sensitive.ecc.b);
POINT_INITIALIZED(C1, c1);
TPMS_ECC_POINT p2;
CRYPT_CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
CRYPT_ECC_INITIALIZED(D, &key->sensitive.sensitive.ecc.b);
CRYPT_POINT_INITIALIZED(C1, c1);
TPMS_ECC_POINT p2;
TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
TPM2B_DIGEST check;
TPM2B_2ECC z;
@ -204,8 +206,8 @@ LIB_EXPORT TPM_RC CryptEccDecrypt(
if(TPM_ALG_KDF2 != scheme->scheme)
ERROR_EXIT(TPM_RC_SCHEME);
// Generate the Z value
BnPointMult(C1, C1, D, NULL, NULL, E);
BnPointTo2B(&p2, C1, E);
TpmEcc_PointMult(C1, C1, D, NULL, NULL, E);
TpmEcc_PointTo2B(&p2, C1, E);
// Start the hash to check the algorithm
if(0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg))
@ -233,7 +235,7 @@ LIB_EXPORT TPM_RC CryptEccDecrypt(
if(!MemoryEqual2B(&check.b, &c3->b))
ERROR_EXIT(TPM_RC_VALUE);
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}

View File

@ -63,6 +63,8 @@
// key-exchange protocols
#include "Tpm.h"
#include "TpmMath_Util_fp.h"
#include "TpmEcc_Util_fp.h"
#if CC_ZGen_2Phase == YES
@ -80,16 +82,19 @@
// 3. 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
static BOOL avf1(Crypt_Int* bnX, // IN/OUT: the reduced value
Crypt_Int* bnN // IN: the order of the curve
)
{
// compute f = 2^(ceil(ceil(log2(n)) / 2))
int f = (BnSizeInBits(bnN) + 1) / 2;
int f = (ExtMath_SizeInBits(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
ExtMath_MaskBits(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);
if(!ExtMath_SetBit(bnX, f))
{
FAIL(FATAL_ERROR_CRYPTO);
}
return TRUE;
}
@ -113,16 +118,15 @@ static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point
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);
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_POINT_VAR(pQeA);
CRYPT_POINT_INITIALIZED(pQeB, QeB);
CRYPT_POINT_INITIALIZED(pQsB, QsB);
CRYPT_ECC_NUM(bnTa);
CRYPT_ECC_INITIALIZED(bnDeA, deA);
CRYPT_ECC_INITIALIZED(bnDsA, dsA);
CRYPT_ECC_NUM(bnN);
CRYPT_ECC_NUM(bnXeB);
TPM_RC retVal;
//
// Parameter checks
@ -130,7 +134,6 @@ static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point
ERROR_EXIT(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).
@ -138,7 +141,8 @@ static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point
// 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))
if((retVal =
TpmEcc_PointMult(pQeA, ExtEcc_CurveGetG(curveId), bnDeA, NULL, NULL, E))
!= TPM_RC_SUCCESS)
goto Exit;
@ -146,19 +150,24 @@ static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point
// 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);
ExtMath_Copy(bnTa, ExtEcc_PointX(pQeA));
avf1(bnTa, bnN);
// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
BnModMult(bnTa, bnDsA, bnTa, bnN);
ExtMath_ModMult(bnTa, bnDsA, bnTa, bnN);
// now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
BnAdd(bnTa, bnTa, bnDeA);
BnMod(bnTa, bnN);
ExtMath_Add(bnTa, bnTa, bnDeA);
ExtMath_Mod(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))
if(!ExtMath_IsEqualWord(ExtEcc_CurveGetCofactor(curveId), 1))
// Cofactor is not 1 so compute Ta := Ta * h mod n
BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C));
ExtMath_ModMult(bnTa,
bnTa,
ExtEcc_CurveGetCofactor(curveId),
ExtEcc_CurveGetOrder(curveId));
// Now that 'tA' is (h * 'tA' mod n)
// 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
@ -166,17 +175,19 @@ static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point
avf1(bnXeB, bnN);
// QsB := [XeB]QsB
BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E);
BnEccAdd(pQeB, pQeB, pQsB, E);
TpmEcc_PointMult(pQsB, pQsB, bnXeB, NULL, NULL, E);
ExtEcc_PointAdd(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))
TpmEcc_PointMult(pQeB, pQeB, bnTa, NULL, NULL, E);
if(ExtEcc_IsInfinityPoint(pQeB))
ERROR_EXIT(TPM_RC_NO_RESULT);
// Convert BIGNUM E to TPM2B E
BnPointTo2B(outZ, pQeB, E);
// Convert Crypt_Int* E to TPM2B E
TpmEcc_PointTo2B(outZ, pQeB, E);
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -195,12 +206,12 @@ static TPM_RC C_2_2_ECDH(TPMS_ECC_POINT* outZs, // OUT: Zs
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);
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_ECC_INITIALIZED(bnAs, dsA);
CRYPT_ECC_INITIALIZED(bnAe, deA);
CRYPT_POINT_INITIALIZED(ecBs, QsB);
CRYPT_POINT_INITIALIZED(ecBe, QeB);
CRYPT_POINT_VAR(ecZ);
TPM_RC retVal;
//
// Parameter checks
@ -210,18 +221,18 @@ static TPM_RC C_2_2_ECDH(TPMS_ECC_POINT* outZs, // OUT: Zs
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);
retVal = TpmEcc_PointMult(ecZ, ecBs, bnAs, NULL, NULL, E);
if(retVal == TPM_RC_SUCCESS)
{
// Convert the Zs value.
BnPointTo2B(outZs, ecZ, E);
TpmEcc_PointTo2B(outZs, ecZ, E);
// Do the point multiply for the Ze value ([deA]QeB)
retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E);
retVal = TpmEcc_PointMult(ecZ, ecBe, bnAe, NULL, NULL, E);
if(retVal == TPM_RC_SUCCESS)
BnPointTo2B(outZe, ecZ, E);
TpmEcc_PointTo2B(outZe, ecZ, E);
}
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -277,10 +288,10 @@ LIB_EXPORT TPM_RC CryptEcc2PhaseKeyExchange(
//*** ComputeWForSM2()
// Compute the value for w used by SM2
static UINT32 ComputeWForSM2(bigCurve E)
static UINT32 ComputeWForSM2(TPM_ECC_CURVE curveId)
{
// w := ceil(ceil(log2(n)) / 2) - 1
return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1);
return (ExtMath_MostSigBitNum(ExtEcc_CurveGetOrder(curveId)) / 2 - 1);
}
//*** avfSm2()
@ -290,19 +301,21 @@ static UINT32 ComputeWForSM2(bigCurve E)
// 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
)
static Crypt_Int* avfSm2(Crypt_Int* 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
ExtMath_MaskBits(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);
if(!ExtMath_SetBit(bn, w))
{
FAIL(FATAL_ERROR_CRYPTO);
}
return bn;
}
@ -328,60 +341,62 @@ LIB_EXPORT TPM_RC SM2KeyExchange(
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);
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_ECC_INITIALIZED(dsA, dsAIn);
CRYPT_ECC_INITIALIZED(deA, deAIn);
CRYPT_POINT_INITIALIZED(QsB, QsBIn);
CRYPT_POINT_INITIALIZED(QeB, QeBIn);
CRYPT_INT_WORD_INITIALIZED(One, 1);
CRYPT_POINT_VAR(QeA);
CRYPT_ECC_NUM(XeB);
CRYPT_POINT_VAR(Z);
CRYPT_ECC_NUM(Ta);
CRYPT_ECC_NUM(QeA_X);
UINT32 w;
TPM_RC retVal = TPM_RC_NO_RESULT;
//
// Parameter checks
if(E == NULL)
ERROR_EXIT(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);
w = ComputeWForSM2(curveId);
// Compute the public ephemeral key pQeA = [de,A]G
if(!BnEccModMult(QeA, CurveGetG(C), deA, E))
if(!ExtEcc_PointMultiply(QeA, ExtEcc_CurveGetG(curveId), 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));
ExtMath_Copy(QeA_X, ExtEcc_PointX(QeA)); // create mutable copy
ExtMath_Multiply(Ta, deA, avfSm2(QeA_X, w));
// now Ta = dsA + Ta = dsA + deA * avf(XeA)
BnAdd(Ta, dsA, Ta);
BnMod(Ta, CurveGetOrder(C));
ExtMath_Add(Ta, dsA, Ta);
ExtMath_Mod(Ta, ExtEcc_CurveGetOrder(curveId));
// 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))
if(!ExtMath_IsEqualWord(ExtEcc_CurveGetCofactor(curveId), 1))
// Cofactor is not 1 so compute Ta := Ta * h mod n
BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C));
ExtMath_ModMult(
Ta, Ta, ExtEcc_CurveGetCofactor(curveId), ExtEcc_CurveGetOrder(curveId));
// 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))
ExtMath_Copy(XeB, ExtEcc_PointX(QeB));
if(!ExtEcc_PointMultiplyAndAdd(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))
if(!ExtEcc_PointMultiply(Z, Z, Ta, E))
goto Exit;
// Convert BIGNUM E to TPM2B E
BnPointTo2B(outZ, Z, E);
// Convert Crypt_Int* E to TPM2B E
TpmEcc_PointTo2B(outZ, Z, E);
retVal = TPM_RC_SUCCESS;
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
# endif

View File

@ -60,8 +60,10 @@
//** Includes and Defines
#include "Tpm.h"
#include "TpmMath_Util_fp.h"
#include "TpmEcc_Util_fp.h"
#include "TpmEcc_Signature_ECDSA_fp.h" // required for pairwise test in key generation
#include "Helpers_fp.h" // libtpms added
#include "TpmToOsslMath_fp.h" // libtpms added
#if ALG_ECC
//** Functions
@ -108,10 +110,9 @@ void ClearPoint2B(TPMS_ECC_POINT* p // IN: the point
// Return Type: const TPM_ECC_CURVE_METADATA
// NULL curve with the indicated TPM_ECC_CURVE is not implemented
// != NULL pointer to the curve data
LIB_EXPORT const ECC_CURVE *
CryptEccGetParametersByCurveId(
TPM_ECC_CURVE curveId // IN: the curveID
)
LIB_EXPORT const TPM_ECC_CURVE_METADATA* CryptEccGetParametersByCurveId(
TPM_ECC_CURVE curveId // IN: the curveID
)
{
int i;
for(i = 0; i < ECC_CURVE_COUNT; i++)
@ -127,27 +128,17 @@ CryptEccGetParametersByCurveId(
LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve(TPM_ECC_CURVE curveId // IN: the curve
)
{
const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId);
UINT16 keySizeInBits;
const TPM_ECC_CURVE_METADATA* 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;
}
//***CryptEccGetOID()
const BYTE* CryptEccGetOID(TPM_ECC_CURVE curveId)
{
const ECC_CURVE*curve = CryptEccGetParametersByCurveId(curveId);
const TPM_ECC_CURVE_METADATA* curve = CryptEccGetParametersByCurveId(curveId);
return (curve != NULL) ? curve->OID : NULL;
}
@ -161,55 +152,6 @@ LIB_EXPORT TPM_ECC_CURVE CryptEccGetCurveByIndex(UINT16 i)
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;
}
//*** CryptCapGetECCCurve()
// This function returns the list of implemented ECC curves.
@ -267,7 +209,8 @@ const TPMT_ECC_SCHEME* CryptGetCurveSignScheme(
TPM_ECC_CURVE curveId // IN: The curve selector
)
{
const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId);
const TPM_ECC_CURVE_METADATA* curve = CryptEccGetParametersByCurveId(curveId);
if(curve != NULL)
return &(curve->sign);
else
@ -300,7 +243,7 @@ BOOL CryptGenerateR(TPM2B_ECC_PARAMETER* r, // OUT: the generated random
UINT64 currentCount = gr.commitCounter;
UINT16 t1;
//
if(!CryptEccGetParameter(&n, 'n', curveID))
if(!TpmMath_IntTo2B(ExtEcc_CurveGetOrder(curveID), (TPM2B*)&n, 0))
return FALSE;
// If this is the commit phase, use the current value of the commit counter
@ -401,101 +344,72 @@ BOOL CryptEccGetParameters(
TPMS_ALGORITHM_DETAIL_ECC* parameters // OUT: ECC parameters
)
{
const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId);
const ECC_CURVE_DATA *data;
const TPM_ECC_CURVE_METADATA* curve = CryptEccGetParametersByCurveId(curveId);
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);
parameters->kdf = curve->kdf;
parameters->sign = curve->sign;
// BnTo2B(data->prime, &parameters->p.b, 0);
found = found
&& TpmMath_IntTo2B(ExtEcc_CurveGetPrime(curveId),
&parameters->p.b,
parameters->p.t.size);
found = found
&& TpmMath_IntTo2B(ExtEcc_CurveGet_a(curveId), &parameters->a.b,
parameters->p.t.size /* libtpms changed for HLK */);
found = found
&& TpmMath_IntTo2B(ExtEcc_CurveGet_b(curveId), &parameters->b.b,
parameters->p.t.size /* libtpms changed for HLK */);
found = found
&& TpmMath_IntTo2B(ExtEcc_CurveGetGx(curveId),
&parameters->gX.b,
parameters->p.t.size);
found = found
&& TpmMath_IntTo2B(ExtEcc_CurveGetGy(curveId),
&parameters->gY.b,
parameters->p.t.size);
// BnTo2B(data->base.x, &parameters->gX.b, 0);
// BnTo2B(data->base.y, &parameters->gY.b, 0);
found =
found
&& TpmMath_IntTo2B(ExtEcc_CurveGetOrder(curveId), &parameters->n.b, 0);
found =
found
&& TpmMath_IntTo2B(ExtEcc_CurveGetCofactor(curveId), &parameters->h.b, 0);
// if we got into this IF but failed to get a parameter from the external
// library, our crypto systems are broken; enter failure mode.
if(!found)
{
FAIL(FATAL_ERROR_MATHLIBRARY);
}
}
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
)
//*** TpmEcc_IsValidPrivateEcc()
// Checks that 0 < 'x' < 'q'
BOOL TpmEcc_IsValidPrivateEcc(const Crypt_Int* x, // IN: private key to check
const Crypt_EccCurve* E // IN: the curve to check
)
{
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));
BOOL retVal;
retVal =
(!ExtMath_IsZero(x)
&& (ExtMath_UnsignedCmp(x, ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(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);
CRYPT_INT_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d);
return !ExtMath_IsZero(bnD)
&& (ExtMath_UnsignedCmp(bnD, ExtEcc_CurveGetOrder(curveId)) < 0);
}
//*** TpmEcc_PointMult()
@ -511,14 +425,13 @@ LIB_EXPORT BOOL CryptEccIsValidPrivateKey(TPM2B_ECC_PARAMETER* d,
// 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
)
TpmEcc_PointMult(Crypt_Point* R, // OUT: computed point
const Crypt_Point* S, // IN: optional point to multiply by 'd'
const Crypt_Int* d, // IN: scalar for [d]S or [d]G
const Crypt_Point* Q, // IN: optional second point
const Crypt_Int* u, // IN: optional second scalar
const Crypt_EccCurve* E // IN: curve parameters
)
{
BOOL OK;
//
@ -538,24 +451,25 @@ BnPointMult(
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)));
OK = (S == NULL) || ExtEcc_IsPointOnCurve(S, E);
OK = OK && ((Q == NULL) || ExtEcc_IsPointOnCurve(Q, E));
if(!OK)
return TPM_RC_ECC_POINT;
if((d != NULL) && (S == NULL))
S = CurveGetG(AccessCurveData(E));
S = ExtEcc_CurveGetG(ExtEcc_CurveGetCurveId(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);
OK = ExtEcc_PointMultiply(R, Q, u, E);
else
OK = BnEccModMult(R, S, d, E);
OK = ExtEcc_PointMultiply(R, S, d, E);
}
else
{
OK = BnEccModMult2(R, S, d, Q, u, E);
OK = ExtEcc_PointMultiplyAndAdd(R, S, d, Q, u, E);
}
return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT);
}
@ -569,59 +483,59 @@ BnPointMult(
// TRUE(1) success
// FALSE(0) 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
)
BOOL TpmEcc_GenPrivateScalar(
Crypt_Int* dOut, // OUT: the qualified random value
const Crypt_EccCurve* E, // IN: curve for which the private key
// needs to be appropriate
RAND_STATE* rand // IN: state for DRBG
)
{
bigConst order = CurveGetOrder(C);
TPM_ECC_CURVE curveId = ExtEcc_CurveGetCurveId(E);
const Crypt_Int* order = ExtEcc_CurveGetOrder(curveId);
BOOL OK;
UINT32 orderBits = BnSizeInBits(order);
UINT32 orderBits = ExtMath_SizeInBits(order);
UINT32 orderBytes = BITS_TO_BYTES(orderBits);
BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
BN_VAR(nMinus1, MAX_ECC_KEY_BITS);
CRYPT_INT_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
CRYPT_INT_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);
OK = BnGetRandomBits((bigNum)bnExtraBits, (orderBytes * 8) + 64, rand); // libtpms: keep for now
OK = OK && ExtMath_SubtractWord(nMinus1, order, 1);
OK = OK && ExtMath_Mod(bnExtraBits, nMinus1);
OK = OK && ExtMath_AddWord(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
)
BOOL TpmEcc_GenPrivateScalar(
Crypt_Int* dOut, // OUT: the qualified random value
const Crypt_EccCurve* E, // IN: curve for which the private key
// needs to be appropriate
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
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);
TPM_ECC_CURVE curveId = ExtEcc_CurveGetCurveId(E);
const Crypt_Int* order = ExtEcc_CurveGetOrder(curveId);
BOOL OK;
UINT32 orderBits = ExtMath_SizeInBits(order);
UINT32 orderBytes = BITS_TO_BYTES(orderBits);
UINT32 requestedBits = 0;
CRYPT_INT_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64);
CRYPT_INT_VAR(nMinus1, MAX_ECC_KEY_BITS);
if (rand == NULL) {
if (noLeadingZeros)
requestedBits = orderBits;
return OpenSSLEccGetPrivate(dOut, G, requestedBits);
return OpenSSLEccGetPrivate((bigNum)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);
OK = BnGetRandomBits((bigNum)bnExtraBits, (orderBytes * 8) + 64, rand); // libtpms: keep for now
OK = OK && ExtMath_SubtractWord(nMinus1, order, 1);
OK = OK && ExtMath_Mod(bnExtraBits, nMinus1);
OK = OK && ExtMath_AddWord(dOut, bnExtraBits, 1);
return OK && !g_inFailureMode;
}
#endif // USE_OPENSSL_FUNCTIONS_EC libtpms added end
@ -630,23 +544,18 @@ BnEccGetPrivate(
//*** TpmEcc_GenerateKeyPair()
// This function gets a private scalar from the source of random bits and does
// the point multiply to get the public key.
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 TpmEcc_GenerateKeyPair(Crypt_Int* bnD, // OUT: private scalar
Crypt_Point* ecQ, // OUT: public point
const Crypt_EccCurve* 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);
OK = TpmEcc_GenPrivateScalar(bnD, E, rand);
// Do a point multiply
OK = OK && BnEccModMult(ecQ, NULL, bnD, E);
if(!OK)
BnSetWord(ecQ->z, 0);
else
BnSetWord(ecQ->z, 1);
OK = OK && ExtEcc_PointMultiply(ecQ, NULL, bnD, E);
return OK;
}
@ -660,38 +569,32 @@ BnEccGenerateKeyPair(
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 TpmEcc_GenerateKeyPair(Crypt_Int* bnD, // OUT: private scalar
Crypt_Point* ecQ, // OUT: public point
const Crypt_EccCurve* 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);
BOOL OK = FALSE;
TPM_ECC_CURVE curveId = ExtEcc_CurveGetCurveId(E);
const Crypt_Int* order = ExtEcc_CurveGetOrder(curveId);
UINT32 orderBits = ExtMath_SizeInBits(order);
BOOL atByteBoundary = (orderBits & 7) == 0;
BOOL noLeadingZeros = atByteBoundary;
CRYPT_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);
OK = TpmEcc_GenPrivateScalar(bnD, 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);
OK = OK && ExtMath_Add(bnD1, bnD, order);
OK = OK && ExtEcc_PointMultiply(ecQ, NULL, bnD1, E);
} else {
OK = OK && BnEccModMult(ecQ, NULL, bnD, E);
OK = OK && ExtEcc_PointMultiply(ecQ, NULL, bnD, E);
}
if(!OK)
BnSetWord(ecQ->z, 0);
else
BnSetWord(ecQ->z, 1);
return OK;
}
@ -706,26 +609,26 @@ LIB_EXPORT TPM_RC CryptEccNewKeyPair(
TPM_ECC_CURVE curveId // IN: the curve for the key
)
{
CURVE_INITIALIZED(E, curveId);
POINT(ecQ);
ECC_NUM(bnD);
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_POINT_VAR(ecQ);
CRYPT_ECC_NUM(bnD);
BOOL OK;
if(E == NULL)
return TPM_RC_CURVE;
TEST(TPM_ALG_ECDH);
OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL);
OK = TpmEcc_GenerateKeyPair(bnD, ecQ, E, NULL);
if(OK)
{
BnPointTo2B(Qout, ecQ, E);
BnTo2B(bnD, &dOut->b, Qout->x.t.size);
TpmEcc_PointTo2B(Qout, ecQ, E);
TpmMath_IntTo2B(bnD, &dOut->b, Qout->x.t.size);
}
else
{
Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0;
}
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
}
@ -766,20 +669,21 @@ LIB_EXPORT TPM_RC CryptEccPointMultiply(
// 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;
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_POINT_INITIALIZED(ecP, Pin);
CRYPT_ECC_INITIALIZED(bnD, dIn); // If dIn is null, then bnD is null
CRYPT_ECC_INITIALIZED(bnU, uIn);
CRYPT_POINT_INITIALIZED(ecQ, Qin);
CRYPT_POINT_VAR(ecR);
TPM_RC retVal;
//
retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E);
retVal = TpmEcc_PointMult(ecR, ecP, bnD, ecQ, bnU, E);
if(retVal == TPM_RC_SUCCESS)
BnPointTo2B(Rout, ecR, E);
TpmEcc_PointTo2B(Rout, ecR, E);
else
ClearPoint2B(Rout);
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -796,12 +700,12 @@ LIB_EXPORT BOOL CryptEccIsPointOnCurve(
TPMS_ECC_POINT* Qin // IN: the point.
)
{
const ECC_CURVE_DATA *C = GetCurveData(curveId);
POINT_INITIALIZED(ecQ, Qin);
CRYPT_CURVE_INITIALIZED(E, curveId);
CRYPT_POINT_INITIALIZED(ecQ, Qin);
BOOL OK;
//
pAssert(Qin != NULL);
OK = (C != NULL && (BnIsOnCurve(ecQ, C)));
OK = (E != NULL && (ExtEcc_IsPointOnCurve(ecQ, E)));
return OK;
}
@ -832,9 +736,9 @@ LIB_EXPORT TPM_RC CryptEccGenerateKey(
// RNG state
)
{
CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID);
ECC_NUM(bnD);
POINT(ecQ);
CRYPT_CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID);
CRYPT_ECC_NUM(bnD);
CRYPT_POINT_VAR(ecQ);
BOOL OK;
TPM_RC retVal;
//
@ -847,18 +751,20 @@ LIB_EXPORT TPM_RC CryptEccGenerateKey(
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);
OK = TpmEcc_GenerateKeyPair(bnD, ecQ, E, rand);
if(OK)
{
BnPointTo2B(&publicArea->unique.ecc, ecQ, E);
BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size);
TpmEcc_PointTo2B(&publicArea->unique.ecc, ecQ, E);
TpmMath_IntTo2B(
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)))
if(OK && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
{
ECC_NUM(bnT);
ECC_NUM(bnS);
CRYPT_ECC_NUM(bnT);
CRYPT_ECC_NUM(bnS);
TPM2B_DIGEST digest;
//
TEST(TPM_ALG_ECDSA);
@ -867,14 +773,15 @@ LIB_EXPORT TPM_RC CryptEccGenerateKey(
DRBG_Generate(NULL, digest.t.buffer, digest.t.size);
if(g_inFailureMode)
return TPM_RC_FAILURE;
BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL);
TpmEcc_SignEcdsa(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;
OK = TpmEcc_ValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest)
== TPM_RC_SUCCESS;
}
# endif
retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -886,10 +793,10 @@ CryptEccIsCurveRuntimeUsable(
TPMI_ECC_CURVE curveId
)
{
CURVE_INITIALIZED(E, curveId);
CRYPT_CURVE_INITIALIZED(E, curveId);
if (E == NULL)
return FALSE;
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return TRUE;
}
// libtpms added end

View File

@ -60,92 +60,102 @@
//** Includes and Defines
#include "Tpm.h"
#include "CryptEccSignature_fp.h"
#include "TpmEcc_Signature_ECDAA_fp.h"
#include "TpmEcc_Signature_ECDSA_fp.h"
#include "TpmEcc_Signature_ECDAA_fp.h"
#include "TpmEcc_Signature_Schnorr_fp.h"
#include "TpmEcc_Signature_SM2_fp.h"
#include "TpmToOsslMath_fp.h" // libtpms added
#if ALG_ECC
/* 10.2.12.2 Utility Functions */
#include "TpmEcc_Util_fp.h"
#include "TpmMath_Util_fp.h"
#include "CryptEccSignature_fp.h"
/* 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
)
#if ALG_ECC
//** Utility Functions
//** Signing Functions
//*** 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.
// Return Type: TPM_RC
// 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;
CRYPT_CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
CRYPT_ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b);
CRYPT_ECC_NUM(bnR);
CRYPT_ECC_NUM(bnS);
TPM_RC retVal = TPM_RC_SCHEME;
//
NOT_REFERENCED(scheme);
if(E == NULL)
ERROR_EXIT(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);
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);
retVal = TpmEcc_SignEcdsa(bnR, bnS, E, bnD, digest, rand);
break;
#if ALG_ECDAA
# if ALG_ECDAA
case TPM_ALG_ECDAA:
retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E,
bnD, digest, scheme, signKey, rand);
bnR = NULL;
retVal = TpmEcc_SignEcdaa(&signature->signature.ecdaa.signatureR,
bnS,
E,
bnD,
digest,
scheme,
signKey,
rand);
bnR = NULL;
break;
#endif
#if ALG_ECSCHNORR
# endif
# if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:
retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest,
signature->signature.ecschnorr.hash,
rand);
retVal = TpmEcc_SignEcSchnorr(
bnR, bnS, E, bnD, digest, signature->signature.ecschnorr.hash, rand);
break;
#endif
#if ALG_SM2
# endif
# if ALG_SM2
case TPM_ALG_SM2:
retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand);
retVal = TpmEcc_SignEcSm2(bnR, bnS, E, bnD, digest, rand);
break;
#endif
# endif
default:
break;
}
// If signature generation worked, convert the results.
if(retVal == TPM_RC_SUCCESS)
{
NUMBYTES orderBytes =
(NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C)));
NUMBYTES orderBytes = (NUMBYTES)BITS_TO_BYTES(
ExtMath_SizeInBits(ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E))));
if(bnR != NULL)
BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes);
TpmMath_IntTo2B(
bnR, &signature->signature.ecdaa.signatureR.b, orderBytes);
if(bnS != NULL)
BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes);
TpmMath_IntTo2B(
bnS, &signature->signature.ecdaa.signatureS.b, orderBytes);
}
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
//********************* Signature Validation ********************
//*** CryptEccValidateSignature()
@ -159,16 +169,18 @@ LIB_EXPORT TPM_RC CryptEccValidateSignature(
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;
CRYPT_CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID);
CRYPT_ECC_NUM(bnR);
CRYPT_ECC_NUM(bnS);
CRYPT_POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc);
const Crypt_Int* order;
TPM_RC retVal;
if(E == NULL)
ERROR_EXIT(TPM_RC_VALUE);
order = CurveGetOrder(AccessCurveData(E));
order = ExtEcc_CurveGetOrder(ExtEcc_CurveGetCurveId(E));
// // Make sure that the scheme is valid
switch(signature->sigAlg)
{
@ -187,37 +199,38 @@ LIB_EXPORT TPM_RC CryptEccValidateSignature(
// 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);
TpmMath_IntFrom2B(bnR, &signature->signature.ecdsa.signatureR.b);
TpmMath_IntFrom2B(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))
if(ExtMath_IsZero(bnR) || ExtMath_IsZero(bnS))
ERROR_EXIT(TPM_RC_SIGNATURE);
if((BnUnsignedCmp(bnS, order) >= 0)
|| (BnUnsignedCmp(bnR, order) >= 0))
if((ExtMath_UnsignedCmp(bnS, order) >= 0)
|| (ExtMath_UnsignedCmp(bnR, order) >= 0))
ERROR_EXIT(TPM_RC_SIGNATURE);
switch(signature->sigAlg)
{
case TPM_ALG_ECDSA:
retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest);
retVal = TpmEcc_ValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest);
break;
#if ALG_ECSCHNORR
# if ALG_ECSCHNORR
case TPM_ALG_ECSCHNORR:
retVal = BnValidateSignatureEcSchnorr(bnR, bnS,
signature->signature.any.hashAlg,
E, ecQ, digest);
retVal = TpmEcc_ValidateSignatureEcSchnorr(
bnR, bnS, signature->signature.any.hashAlg, E, ecQ, digest);
break;
#endif
#if ALG_SM2
# endif
# if ALG_SM2
case TPM_ALG_SM2:
retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest);
retVal = TpmEcc_ValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest);
break;
#endif
# endif
default:
FAIL(FATAL_ERROR_INTERNAL);
}
Exit:
CURVE_FREE(E);
CRYPT_CURVE_FREE(E);
return retVal;
}
@ -248,10 +261,11 @@ LIB_EXPORT TPM_RC CryptEccCommitCompute(
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;
// Normally initialize E as the curve, but
// E means something else in this function
CRYPT_CURVE_INITIALIZED(curve, curveId);
CRYPT_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
@ -269,34 +283,37 @@ LIB_EXPORT TPM_RC CryptEccCommitCompute(
// 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);
CRYPT_ECC_INITIALIZED(bnD, d);
CRYPT_POINT_INITIALIZED(pB, B);
CRYPT_POINT_VAR(pK);
CRYPT_POINT_VAR(pL);
//
pAssert(d != NULL && K != NULL && L != NULL);
if(!BnIsOnCurve(pB, AccessCurveData(curve)))
if(!ExtEcc_IsPointOnCurve(pB, curve))
ERROR_EXIT(TPM_RC_VALUE);
// do the math for K = [d]B
if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS)
if((retVal = TpmEcc_PointMult(pK, pB, bnD, NULL, NULL, curve))
!= TPM_RC_SUCCESS)
goto Exit;
// Convert BN K to TPM2B K
BnPointTo2B(K, pK, curve);
TpmEcc_PointTo2B(K, pK, curve);
// compute L= [r]B after checking for cancel
if(_plat__IsCanceled())
ERROR_EXIT(TPM_RC_CANCELED);
// compute L = [r]B
if(!BnIsValidPrivateEcc(bnR, curve))
if(!TpmEcc_IsValidPrivateEcc(bnR, curve))
ERROR_EXIT(TPM_RC_VALUE);
if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS)
if((retVal = TpmEcc_PointMult(pL, pB, bnR, NULL, NULL, curve))
!= TPM_RC_SUCCESS)
goto Exit;
// Convert BN L to TPM2B L
BnPointTo2B(L, pL, curve);
TpmEcc_PointTo2B(L, pL, curve);
}
if((M != NULL) || (B == NULL))
{
POINT_INITIALIZED(pM, M);
POINT(pE);
CRYPT_POINT_INITIALIZED(pM, M);
CRYPT_POINT_VAR(pE);
//
// Make sure that a place was provided for the result
pAssert(E != NULL);
@ -308,13 +325,14 @@ LIB_EXPORT TPM_RC CryptEccCommitCompute(
// 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)
if((retVal = TpmEcc_PointMult(pE, pM, bnR, NULL, NULL, curve))
!= TPM_RC_SUCCESS)
goto Exit;
// Convert E to 2B format
BnPointTo2B(E, pE, curve);
TpmEcc_PointTo2B(E, pE, curve);
}
Exit:
CURVE_FREE(curve);
CRYPT_CURVE_FREE(curve);
return retVal;
}

View File

@ -61,7 +61,8 @@
#include "Tpm.h"
#include "ExpDCache_fp.h"
#include "Helpers_fp.h"
#include "TpmToOsslMath_fp.h"
#include "BnToOsslMath_fp.h"
#include "TpmMath_Util_fp.h"
#include "config.h"

View File

@ -92,6 +92,14 @@
#include "BnMemory_fp.h"
#include "BnSupport_Interface.h"
// Create a data object backing a Crypt_Point big enough for the given number of
// data bits, per coordinate
#define CRYPT_POINT_BUF(buftypename, bits) BN_POINT_BUF(buftypename, bits)
// Create an instance of a data object underlying Crypt_EccCurve on the stack
// sufficient for given bit size. In our case, all are the same size.
#define CRYPT_CURVE_BUF(buftypename, max_size_in_bits) bigCurveData
// now include the math library functional interface and instantiate the
// Crypt_Int & related types
// TODO_RENAME_INC_FOLDER: This should have a Tpm_Cryptolib_Common component prefix.