/* 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. | |
*/ | |
//** Introduction | |
// | |
// This file contains the math functions that are not implemented in the BnMath | |
// library (yet). These math functions will call the ST MPA library or the | |
// LibTomCrypt library to execute the operations. Since the TPM internal big number | |
// format is identical to the MPA format, no reformatting is required. | |
//** Includes | |
#include "Tpm.h" | |
#ifdef MATH_LIB_LTC | |
#if defined ECC_NIST_P256 && ECC_NIST_P256 == YES && ECC_CURVE_COUNT > 1 | |
#error "LibTomCrypt only supports P256" | |
#endif | |
//** Functions | |
//*** BnModMult() | |
// Does multiply and divide returning the remainder of the divide. | |
LIB_EXPORT BOOL | |
BnModMult( | |
bigNum result, | |
bigConst op1, | |
bigConst op2, | |
bigConst modulus | |
) | |
{ | |
BN_VAR(temp, LARGEST_NUMBER_BITS * 2); | |
// mpa_mul does not allocate from the pool if the result is not the same as | |
// op1 or op2. since this is assured by the stack allocation of 'temp', the | |
// pool pointer can be NULL | |
pAssert(BnGetAllocated(result) >= BnGetSize(modulus)); | |
mpa_mul((mpanum)temp, (const mpanum)op1, (const mpanum)op2, | |
NULL); | |
return BnDiv(NULL, result, temp, modulus); | |
} | |
//*** BnMult() | |
// Multiplies two numbers | |
LIB_EXPORT BOOL | |
BnMult( | |
bigNum result, | |
bigConst multiplicand, | |
bigConst multiplier | |
) | |
{ | |
// Make sure that the mpa_mul function does not allocate anything | |
// from the POOL by eliminating the reason for doing it. | |
BN_VAR(tempResult, LARGEST_NUMBER_BITS * 2); | |
if(result != multiplicand && result != multiplier) | |
tempResult = result; | |
mpa_mul((mpanum)tempResult, (const mpanum)multiplicand, | |
(const mpanum)multiplier, | |
NULL); | |
BnCopy(result, tempResult); | |
return TRUE; | |
} | |
//*** BnDiv() | |
// This function divides two BIGNUM values. The function always returns TRUE. | |
LIB_EXPORT BOOL | |
BnDiv( | |
bigNum quotient, | |
bigNum remainder, | |
bigConst dividend, | |
bigConst divisor | |
) | |
{ | |
MPA_ENTER(10, LARGEST_NUMBER_BITS); | |
pAssert(!BnEqualZero(divisor)); | |
if(BnGetSize(dividend) < BnGetSize(divisor)) | |
{ | |
if(quotient) | |
BnSetWord(quotient, 0); | |
if(remainder) | |
BnCopy(remainder, dividend); | |
} | |
else | |
{ | |
pAssert((quotient == NULL) | |
|| (quotient->allocated >= | |
(unsigned)(dividend->size - divisor->size))); | |
pAssert((remainder == NULL) | |
|| (remainder->allocated >= divisor->size)); | |
mpa_div((mpanum)quotient, (mpanum)remainder, | |
(const mpanum)dividend, (const mpanum)divisor, POOL); | |
} | |
MPA_LEAVE(); | |
return TRUE; | |
} | |
#ifdef TPM_ALG_RSA | |
//*** BnGcd() | |
// Get the greatest common divisor of two numbers | |
LIB_EXPORT BOOL | |
BnGcd( | |
bigNum gcd, // OUT: the common divisor | |
bigConst number1, // IN: | |
bigConst number2 // IN: | |
) | |
{ | |
MPA_ENTER(20, LARGEST_NUMBER_BITS); | |
// | |
mpa_gcd((mpanum)gcd, (mpanum)number1, (mpanum)number2, POOL); | |
MPA_LEAVE(); | |
return TRUE; | |
} | |
//***BnModExp() | |
// Do modular exponentiation using BIGNUM values. The conversion from a bignum_t | |
// to a BIGNUM is trivial as they are based on the same structure | |
LIB_EXPORT BOOL | |
BnModExp( | |
bigNum result, // OUT: the result | |
bigConst number, // IN: number to exponentiate | |
bigConst exponent, // IN: | |
bigConst modulus // IN: | |
) | |
{ | |
MPA_ENTER(20, LARGEST_NUMBER_BITS); | |
BN_VAR(bnR, MAX_RSA_KEY_BITS); | |
BN_VAR(bnR2, MAX_RSA_KEY_BITS); | |
mpa_word_t n_inv; | |
mpa_word_t ffmCtx[mpa_fmm_context_size_in_U32(MAX_RSA_KEY_BITS)]; | |
// | |
mpa_init_static_fmm_context((mpa_fmm_context_base *)ffmCtx, | |
BYTES_TO_CRYPT_WORDS(sizeof(ffmCtx))); | |
// Generate modular form | |
if(mpa_compute_fmm_context((const mpanum)modulus, (mpanum)bnR, | |
(mpanum)bnR2, &n_inv, POOL) != 0) | |
FAIL(FATAL_ERROR_INTERNAL); | |
// Do exponentiation | |
mpa_exp_mod((mpanum)result, (const mpanum)number, (const mpanum)exponent, | |
(const mpanum)modulus, (const mpanum)bnR, (const mpanum)bnR2, | |
n_inv, POOL); | |
MPA_LEAVE(); | |
return TRUE; | |
} | |
//*** BnModInverse() | |
// Modular multiplicative inverse | |
LIB_EXPORT BOOL | |
BnModInverse( | |
bigNum result, | |
bigConst number, | |
bigConst modulus | |
) | |
{ | |
BOOL retVal; | |
MPA_ENTER(10, LARGEST_NUMBER_BITS); | |
retVal = (mpa_inv_mod((mpanum)result, (const mpanum)number, | |
(const mpanum)modulus, POOL) == 0); | |
MPA_LEAVE(); | |
return retVal; | |
} | |
#endif // TPM_ALG_RSA | |
#ifdef TPM_ALG_ECC | |
//*** BnEccModMult() | |
// This function does a point multiply of the form R = [d]S | |
// return type: BOOL | |
// FALSE failure in operation; treat as result being point at infinity | |
LIB_EXPORT BOOL | |
BnEccModMult( | |
bigPoint R, // OUT: computed point | |
pointConst S, // IN: point to multiply by 'd' | |
bigConst d, // IN: scalar for [d]S | |
bigCurve E | |
) | |
{ | |
MPA_ENTER(30, MAX_ECC_KEY_BITS * 2); | |
// The point multiply in LTC seems to need a large reciprocal for | |
// intermediate results | |
POINT_VAR(result, MAX_ECC_KEY_BITS * 4); | |
BOOL OK; | |
// | |
(POOL); // Avoid compiler warning | |
if(S == NULL) | |
S = CurveGetG(AccessCurveData(E)); | |
OK = (ltc_ecc_mulmod((mpanum)d, (ecc_point *)S, | |
(ecc_point *)result, (void *)CurveGetPrime(E), 1) | |
== CRYPT_OK); | |
OK = OK && !BnEqualZero(result->z); | |
if(OK) | |
BnPointCopy(R, result); | |
MPA_LEAVE(); | |
return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; | |
} | |
//*** BnEccModMult2() | |
// This function does a point multiply of the form R = [d]S + [u]Q | |
// return type: BOOL | |
// FALSE failure in operation; treat as result being point at infinity | |
LIB_EXPORT BOOL | |
BnEccModMult2( | |
bigPoint R, // OUT: computed point | |
pointConst S, // IN: first point (optional) | |
bigConst d, // IN: scalar for [d]S or [d]G | |
pointConst Q, // IN: second point | |
bigConst u, // IN: second scalar | |
bigCurve E // IN: curve | |
) | |
{ | |
MPA_ENTER(80, MAX_ECC_KEY_BITS); | |
BOOL OK; | |
// The point multiply in LTC seems to need a large reciprocal for | |
// intermediate results | |
POINT_VAR(result, MAX_ECC_KEY_BITS * 4); | |
// | |
(POOL); // Avoid compiler warning | |
if(S == NULL) | |
S = CurveGetG(AccessCurveData(E)); | |
OK = (ltc_ecc_mul2add((ecc_point *)S, (mpanum)d, (ecc_point *)Q, (mpanum)u, | |
(ecc_point *)result, (mpanum)CurveGetPrime(E)) | |
== CRYPT_OK); | |
OK = OK && !BnEqualZero(result->z); | |
if(OK) | |
BnPointCopy(R, result); | |
MPA_LEAVE(); | |
return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; | |
} | |
//*** BnEccAdd() | |
// This function does addition of two points. Since this is not implemented | |
// in LibTomCrypt() will try to trick it by doing multiply with scalar of 1. | |
// I have no idea if this will work and it's not needed unless MQV or the SM2 | |
// variant is enabled. | |
// return type: BOOL | |
// FALSE failure in operation; treat as result being point at infinity | |
LIB_EXPORT BOOL | |
BnEccAdd( | |
bigPoint R, // OUT: computed point | |
pointConst S, // IN: point to multiply by 'd' | |
pointConst Q, // IN: second point | |
bigCurve E // IN: curve | |
) | |
{ | |
BN_WORD_INITIALIZED(one, 1); | |
return BnEccModMult2(R, S, one, Q, one, E); | |
} | |
#endif // TPM_ALG_ECC | |
#endif // MATH_LIB_LTC |