blob: 5e75f8d75a99c63de55b95bedee14f757771d47e [file] [log] [blame]
/* 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"
#if 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