/********************************************************************************/ /* */ /* For defining the internal BIGNUM structure */ /* 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, 2016 - 2023 */ /* */ /********************************************************************************/ //** Introduction // This file contains the definitions needed for defining the internal bigNum // structure. // A bigNum is a pointer to a structure. The structure has three fields. The // last field is and array (d) of crypt_uword_t. Each word is in machine format // (big- or little-endian) with the words in ascending significance (i.e. words // in little-endian order). This is the order that seems to be used in every // big number library in the worlds, so... // // The first field in the structure (allocated) is the number of words in 'd'. // This is the upper limit on the size of the number that can be held in the // structure. This differs from libraries like OpenSSL as this is not intended // to deal with numbers of arbitrary size; just numbers that are needed to deal // with the algorithms that are defined in the TPM implementation. // // The second field in the structure (size) is the number of significant words // in 'n'. When this number is zero, the number is zero. The word at used-1 should // never be zero. All words between d[size] and d[allocated-1] should be zero. //** Defines #ifndef _BN_NUMBERS_H #define _BN_NUMBERS_H // TODO_RENAME_INC_FOLDER:private refers to the TPM_CoreLib private headers #include "TpmAlgorithmDefines.h" #include "GpMacros.h" // required for TpmFail_fp.h #include "Capabilities.h" #include "TpmTypes.h" // requires capabilities & GpMacros // These are the basic big number formats. This is convertible to the library- // specific format without too much difficulty. For the math performed using // these numbers, the value is always positive. #define BN_STRUCT_DEF(struct_type, count) \ struct st_##struct_type##_t \ { \ crypt_uword_t allocated; \ crypt_uword_t size; \ crypt_uword_t d[count]; \ } typedef BN_STRUCT_DEF(bnroot, 1) bignum_t; #ifndef bigNum typedef bignum_t* bigNum; typedef const bignum_t* bigConst; #endif //bigNum extern const bignum_t BnConstZero; // The Functions to access the properties of a big number. // Get number of allocated words #define BnGetAllocated(x) (unsigned)((x)->allocated) // Get number of words used #define BnGetSize(x) ((x)->size) // Get a pointer to the data array #define BnGetArray(x) ((crypt_uword_t*)&((x)->d[0])) // Get the nth word of a bigNum (zero-based) #define BnGetWord(x, i) (crypt_uword_t)((x)->d[i]) // Some things that are done often. // Test to see if a bignum_t is equal to zero #define BnEqualZero(bn) (BnGetSize(bn) == 0) // Test to see if a bignum_t is equal to a word type #define BnEqualWord(bn, word) \ ((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word)) // Determine if a bigNum is even. A zero is even. Although the // indication that a number is zero is that its size is zero, // all words of the number are 0 so this test works on zero. #define BnIsEven(n) ((BnGetWord(n, 0) & 1) == 0) // The macros below are used to define bigNum values of the required // size. The values are allocated on the stack so they can be // treated like simple local values. // This will call the initialization function for a defined bignum_t. // This sets the allocated and used fields and clears the words of 'n'. #define BN_INIT(name) \ (bigNum) BnInit((bigNum) & (name), BYTES_TO_CRYPT_WORDS(sizeof(name.d))) #define CRYPT_WORDS(bytes) BYTES_TO_CRYPT_WORDS(bytes) #define MIN_ALLOC(bytes) (CRYPT_WORDS(bytes) < 1 ? 1 : CRYPT_WORDS(bytes)) #define BN_CONST(name, bytes, initializer) \ typedef const struct name##_type \ { \ crypt_uword_t allocated; \ crypt_uword_t size; \ crypt_uword_t d[MIN_ALLOC(bytes)]; \ } name##_type; \ name##_type name = {MIN_ALLOC(bytes), CRYPT_WORDS(bytes), {initializer}}; #define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1) // Create a structure of the correct size. #define BN_STRUCT(struct_type, bits) \ BN_STRUCT_DEF(struct_type, BN_STRUCT_ALLOCATION(bits)) // Define a bigNum type with a specific allocation #define BN_TYPE(name, bits) typedef BN_STRUCT(name, bits) bn_##name##_t // This creates a local bigNum variable of a specific size and // initializes it from a TPM2B input parameter. #define BN_INITIALIZED(name, bits, initializer) \ BN_STRUCT(name, bits) name##_; \ bigNum name = TpmMath_IntFrom2B(BN_INIT(name##_), (const TPM2B*)initializer) // Create a local variable that can hold a number with 'bits' #define BN_VAR(name, bits) \ BN_STRUCT(name, bits) _##name; \ bigNum name = BN_INIT(_##name) // Create a type that can hold the largest number defined by the // implementation. #define BN_MAX(name) BN_VAR(name, LARGEST_NUMBER_BITS) #define BN_MAX_INITIALIZED(name, initializer) \ BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer) // A word size value is useful #define BN_WORD(name) BN_VAR(name, RADIX_BITS) // This is used to create a word-size bigNum and initialize it with // an input parameter to a function. #define BN_WORD_INITIALIZED(name, initial) \ BN_STRUCT(RADIX_BITS) name##_; \ bigNum name = \ BnInitializeWord((bigNum)&name##_, BN_STRUCT_ALLOCATION(RADIX_BITS), initial) // ECC-Specific Values // This is the format for a point. It is always in affine format. The Z value is // carried as part of the point, primarily to simplify the interface to the support // library. Rather than have the interface layer have to create space for the // point each time it is used... // The x, y, and z values are pointers to bigNum values and not in-line versions of // the numbers. This is a relic of the days when there was no standard TPM format // for the numbers typedef struct _bn_point_t { bigNum x; bigNum y; bigNum z; } bn_point_t; typedef bn_point_t* bigPoint; typedef const bn_point_t* pointConst; typedef struct constant_point_t { bigConst x; bigConst y; bigConst z; } constant_point_t; // 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 // ========================= // A cryptographic elliptic curve is a mathematical set (Group) of points that // satisfy the group equation and are generated by linear multiples of some // initial "generator" point (Gx,Gy). // // The TPM code supports ECC Curves that satisfy equations of the following // form: // // (y^2 = x^3 + a*x + b) mod p // // A particular cryptographic curve is fully described by the following // parameters: // // | Name | Meaning | // | :------ | :---------------------------------------------------------------------------------- | // | p | curve prime | // | a, b | equation coefficients | // | (Gx,Gy) | X and Y coordinates of the generator point. | // | n | the order (size) of the generated group. n must be prime. | // | h | the cofactor of the group size to the full set of points for a particular equation. | // // The group of constants to describe a particular ECC Curve (such as NIST P256 // or P384) are contained in TPMBN_ECC_CURVE_CONSTANTS objects. In the // TpmBigNum library these constants are always stored in TPM's internal BN // (bigNum) format. // // Other math libraries are expected to provide these as compile time constants // in a format they can efficiently consume at runtime. // Structure for the curve parameters. This is an analog to the // 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 } 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 // a pointer to an TPMBN_ECC_CURVE_CONSTANTS structure as well as some other bits. For those // cases, the AccessCurveConstants function is used in the code to first get the pointer // 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. 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. #define BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) \ (((UINT32)(a) << 24) + ((UINT32)(b) << 16) + ((UINT32)(c) << 8) + ((UINT32)(d))) #define BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h) \ (((UINT64)(a) << 56) + ((UINT64)(b) << 48) + ((UINT64)(c) << 40) \ + ((UINT64)(d) << 32) + ((UINT64)(e) << 24) + ((UINT64)(f) << 16) \ + ((UINT64)(g) << 8) + ((UINT64)(h))) // These macros are used for data initialization of big number ECC constants // These two macros combine a macro for data definition with a macro for // structure initialization. The 'a' parameter is a macro that gives numbers to // each of the bytes of the initializer and defines where each of the numberd // bytes will show up in the final structure. The 'b' value is a structure that // contains the requisite number of bytes in big endian order. S, the MJOIN // and JOIND macros will combine a macro defining a data layout with a macro defining // the data to be places. Generally, these macros will only need expansion when // CryptEccData.c gets compiled. #define JOINED(a, b) a b #define MJOIN(a, b) a b #if RADIX_BYTES == 64 # define B8_TO_BN(a, b, c, d, e, f, g, h) \ ((((((((((((((((UINT64)a) << 8) | (UINT64)b) << 8) | (UINT64)c) << 8) \ | (UINT64)d) \ << 8) \ | (UINT64)e) \ << 8) \ | (UINT64)f) \ << 8) \ | (UINT64)g) \ << 8) \ | (UINT64)h) # define B1_TO_BN(a) B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a) # define B2_TO_BN(a, b) B8_TO_BN(0, 0, 0, 0, 0, 0, a, b) # define B3_TO_BN(a, b, c) B8_TO_BN(0, 0, 0, 0, 0, a, b, c) # define B4_TO_BN(a, b, c, d) B8_TO_BN(0, 0, 0, 0, a, b, c, d) # define B5_TO_BN(a, b, c, d, e) B8_TO_BN(0, 0, 0, a, b, c, d, e) # define B6_TO_BN(a, b, c, d, e, f) B8_TO_BN(0, 0, a, b, c, d, e, f) # define B7_TO_BN(a, b, c, d, e, f, g) B8_TO_BN(0, a, b, c, d, e, f, g) #else # define B1_TO_BN(a) B4_TO_BN(0, 0, 0, a) # define B2_TO_BN(a, b) B4_TO_BN(0, 0, a, b) # define B3_TO_BN(a, b, c) B4_TO_BN(0, a, b, c) # define B4_TO_BN(a, b, c, d) \ (((((((UINT32)a << 8) | (UINT32)b) << 8) | (UINT32)c) << 8) | (UINT32)d) # define B5_TO_BN(a, b, c, d, e) B4_TO_BN(b, c, d, e), B1_TO_BN(a) # define B6_TO_BN(a, b, c, d, e, f) B4_TO_BN(c, d, e, f), B2_TO_BN(a, b) # define B7_TO_BN(a, b, c, d, e, f, g) B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c) # define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d) #endif #endif // _BN_NUMBERS_H