diff options
Diffstat (limited to 'src/tpm2/MathOnByteBuffers.c')
-rw-r--r-- | src/tpm2/MathOnByteBuffers.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/tpm2/MathOnByteBuffers.c b/src/tpm2/MathOnByteBuffers.c new file mode 100644 index 0000000..7a0b9da --- /dev/null +++ b/src/tpm2/MathOnByteBuffers.c @@ -0,0 +1,266 @@ +/********************************************************************************/ +/* */ +/* Math functions performed with canonical integers in byte buffers */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: MathOnByteBuffers.c 1519 2019-11-15 20:43:51Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +/* 9.11 MathOnByteBuffers.c */ +/* 9.11.1 Introduction */ +/* This file contains implementation of the math functions that are performed with canonical + integers in byte buffers. The canonical integer is big-endian bytes. */ +#include "Tpm.h" +/* 9.11.2.1 UnsignedCmpB */ +/* This function compare two unsigned values. The values are byte-aligned, big-endian numbers (e.g, + a hash). */ +/* Return Values Meaning */ +/* 1 if (a > b) */ +/* 0 if (a = b) */ +/* -1 if (a < b) */ +LIB_EXPORT int +UnsignedCompareB( + UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a + UINT32 bSize, // IN: size of b + const BYTE *b // IN: b + ) +{ + UINT32 i; + if(aSize > bSize) + return 1; + else if(aSize < bSize) + return -1; + else + { + for(i = 0; i < aSize; i++) + { + if(a[i] != b[i]) + return (a[i] > b[i]) ? 1 : -1; + } + } + return 0; +} +/* 9.11.2.2 SignedCompareB() */ +/* Compare two signed integers: */ +/* Return Values Meaning */ +/* 1 if a > b */ +/* 0 if a = b */ +/* -1 if a < b */ +int +SignedCompareB( + const UINT32 aSize, // IN: size of a + const BYTE *a, // IN: a buffer + const UINT32 bSize, // IN: size of b + const BYTE *b // IN: b buffer + ) +{ + int signA, signB; // sign of a and b + // For positive or 0, sign_a is 1 + // for negative, sign_a is 0 + signA = ((a[0] & 0x80) == 0) ? 1 : 0; + // For positive or 0, sign_b is 1 + // for negative, sign_b is 0 + signB = ((b[0] & 0x80) == 0) ? 1 : 0; + if(signA != signB) + { + return signA - signB; + } + if(signA == 1) + // do unsigned compare function + return UnsignedCompareB(aSize, a, bSize, b); + else + // do unsigned compare the other way + return 0 - UnsignedCompareB(aSize, a, bSize, b); +} +/* 9.11.3.3 ModExpB */ +/* This function is used to do modular exponentiation in support of RSA. The most typical uses are: + c = m^e mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e + parameter of the function will contain the private exponent d instead of the public exponent + e. */ +/* If the results will not fit in the provided buffer, an error is returned + (CRYPT_ERROR_UNDERFLOW). If the results is smaller than the buffer, the results is + de-normalized. */ +/* This version is intended for use with RSA and requires that m be less than n. */ +/* Error Returns Meaning */ +/* TPM_RC_SIZE number to exponentiate is larger than the modulus */ +/* TPM_RC_NO_RESULT result will not fit into the provided buffer */ +TPM_RC +ModExpB( + UINT32 cSize, // IN: the size of the output buffer. It will + // need to be the same size as the modulus + BYTE *c, // OUT: the buffer to receive the results + // (c->size must be set to the maximum size + // for the returned value) + const UINT32 mSize, + const BYTE *m, // IN: number to exponentiate + const UINT32 eSize, + const BYTE *e, // IN: power + const UINT32 nSize, + const BYTE *n // IN: modulus + ) +{ + BN_MAX(bnC); + BN_MAX(bnM); + BN_MAX(bnE); + BN_MAX(bnN); + NUMBYTES tSize = (NUMBYTES)nSize; + TPM_RC retVal = TPM_RC_SUCCESS; + // Convert input parameters + BnFromBytes(bnM, m, (NUMBYTES)mSize); + BnFromBytes(bnE, e, (NUMBYTES)eSize); + BnFromBytes(bnN, n, (NUMBYTES)nSize); + // Make sure that the output is big enough to hold the result + // and that 'm' is less than 'n' (the modulus) + if(cSize < nSize) + ERROR_RETURN(TPM_RC_NO_RESULT); + if(BnUnsignedCmp(bnM, bnN) >= 0) + ERROR_RETURN(TPM_RC_SIZE); + BnModExp(bnC, bnM, bnE, bnN); + BnToBytes(bnC, c, &tSize); + Exit: + return retVal; +} +/* 9.11.2.4 DivideB() */ +/* Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r + is not needed, then the pointer to them may be set to NULL. */ +/* Error Returns Meaning */ +/* TPM_RC_NO_RESULT q or r is too small to receive the result */ +LIB_EXPORT TPM_RC +DivideB( + const TPM2B *n, // IN: numerator + const TPM2B *d, // IN: denominator + TPM2B *q, // OUT: quotient + TPM2B *r // OUT: remainder + ) +{ + BN_MAX_INITIALIZED(bnN, n); + BN_MAX_INITIALIZED(bnD, d); + BN_MAX(bnQ); + BN_MAX(bnR); + // + // Do divide with converted values + BnDiv(bnQ, bnR, bnN, bnD); + // Convert the BIGNUM result back to 2B format using the size of the original + // number + if(q != NULL) + if(!BnTo2B(bnQ, q, q->size)) + return TPM_RC_NO_RESULT; + if(r != NULL) + if(!BnTo2B(bnR, r, r->size)) + return TPM_RC_NO_RESULT; + return TPM_RC_SUCCESS; +} +/* 9.11.2.5 AdjustNumberB() */ +/* Remove/add leading zeros from a number in a TPM2B. Will try to make the number by adding or + removing leading zeros. If the number is larger than the requested size, it will make the number + as small as possible. Setting requestedSize to zero is equivalent to requesting that the number + be normalized. */ +UINT16 +AdjustNumberB( + TPM2B *num, + UINT16 requestedSize + ) +{ + BYTE *from; + UINT16 i; + // See if number is already the requested size + if(num->size == requestedSize) + return requestedSize; + from = num->buffer; + if (num->size > requestedSize) + { + // This is a request to shift the number to the left (remove leading zeros) + // Find the first non-zero byte. Don't look past the point where removing + // more zeros would make the number smaller than requested, and don't throw + // away any significant digits. + for(i = num->size; *from == 0 && i > requestedSize; from++, i--); + if(i < num->size) + { + num->size = i; + MemoryCopy(num->buffer, from, i); + } + } + // This is a request to shift the number to the right (add leading zeros) + else + { + MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size); + MemorySet(num->buffer, 0, requestedSize- num->size); + num->size = requestedSize; + } + return num->size; +} + +/* 9.11.2.6 ShiftLeft() */ +/* This function shifts a byte buffer (a TPM2B) one byte to the left. That is, the most significant + bit of the most significant byte is lost. */ +TPM2B * +ShiftLeft( + TPM2B *value // IN/OUT: value to shift and shifted value out + ) +{ + UINT16 count = value->size; + BYTE *buffer = value->buffer; + if(count > 0) + { + for(count -= 1; count > 0; buffer++, count--) + { + buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0); + } + *buffer <<= 1; + } + return value; +} |