• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or other
22  *  materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //** Introduction
37 //
38 // This file contains the math functions that are not implemented in the BnMath
39 // library (yet). These math functions will call the ST MPA library or the
40 // LibTomCrypt library to execute the operations. Since the TPM internal big number
41 // format is identical to the MPA format, no reformatting is required.
42 
43 //** Includes
44 #include "Tpm.h"
45 
46 #ifdef MATH_LIB_LTC
47 
48 #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES && ECC_CURVE_COUNT > 1
49 #error "LibTomCrypt only supports P256"
50 #endif
51 
52 //** Functions
53 
54 //*** BnModMult()
55 // Does multiply and divide returning the remainder of the divide.
56 LIB_EXPORT BOOL
BnModMult(bigNum result,bigConst op1,bigConst op2,bigConst modulus)57 BnModMult(
58     bigNum              result,
59     bigConst            op1,
60     bigConst            op2,
61     bigConst            modulus
62     )
63 {
64     BN_VAR(temp, LARGEST_NUMBER_BITS * 2);
65     // mpa_mul does not allocate from the pool if the result is not the same as
66     // op1 or op2. since this is assured by the stack allocation of 'temp', the
67     // pool pointer can be NULL
68     pAssert(BnGetAllocated(result) >= BnGetSize(modulus));
69     mpa_mul((mpanum)temp, (const mpanum)op1, (const mpanum)op2,
70             NULL);
71     return BnDiv(NULL, result, temp, modulus);
72 }
73 
74 //*** BnMult()
75 // Multiplies two numbers
76 LIB_EXPORT BOOL
BnMult(bigNum result,bigConst multiplicand,bigConst multiplier)77 BnMult(
78     bigNum               result,
79     bigConst             multiplicand,
80     bigConst             multiplier
81     )
82 {
83     // Make sure that the mpa_mul function does not allocate anything
84     // from the POOL by eliminating the reason for doing it.
85     BN_VAR(tempResult, LARGEST_NUMBER_BITS * 2);
86     if(result != multiplicand && result != multiplier)
87         tempResult = result;
88     mpa_mul((mpanum)tempResult, (const mpanum)multiplicand,
89             (const mpanum)multiplier,
90             NULL);
91     BnCopy(result, tempResult);
92     return TRUE;
93 }
94 
95 //*** BnDiv()
96 // This function divides two BIGNUM values. The function always returns TRUE.
97 LIB_EXPORT BOOL
BnDiv(bigNum quotient,bigNum remainder,bigConst dividend,bigConst divisor)98 BnDiv(
99     bigNum               quotient,
100     bigNum               remainder,
101     bigConst             dividend,
102     bigConst             divisor
103     )
104 {
105     MPA_ENTER(10, LARGEST_NUMBER_BITS);
106     pAssert(!BnEqualZero(divisor));
107     if(BnGetSize(dividend) < BnGetSize(divisor))
108     {
109         if(quotient)
110             BnSetWord(quotient, 0);
111         if(remainder)
112             BnCopy(remainder, dividend);
113     }
114     else
115     {
116         pAssert((quotient == NULL)
117                 || (quotient->allocated >=
118                         (unsigned)(dividend->size - divisor->size)));
119         pAssert((remainder == NULL)
120                 || (remainder->allocated >= divisor->size));
121         mpa_div((mpanum)quotient, (mpanum)remainder,
122                 (const mpanum)dividend, (const mpanum)divisor, POOL);
123     }
124     MPA_LEAVE();
125     return TRUE;
126 }
127 
128 #ifdef TPM_ALG_RSA
129 //*** BnGcd()
130 // Get the greatest common divisor of two numbers
131 LIB_EXPORT BOOL
BnGcd(bigNum gcd,bigConst number1,bigConst number2)132 BnGcd(
133     bigNum      gcd,            // OUT: the common divisor
134     bigConst    number1,        // IN:
135     bigConst    number2         // IN:
136     )
137 {
138     MPA_ENTER(20, LARGEST_NUMBER_BITS);
139 //
140     mpa_gcd((mpanum)gcd, (mpanum)number1, (mpanum)number2, POOL);
141     MPA_LEAVE();
142     return TRUE;
143 }
144 
145 //***BnModExp()
146 // Do modular exponentiation using BIGNUM values. The conversion from a bignum_t
147 // to a BIGNUM is trivial as they are based on the same structure
148 LIB_EXPORT BOOL
BnModExp(bigNum result,bigConst number,bigConst exponent,bigConst modulus)149 BnModExp(
150     bigNum               result,         // OUT: the result
151     bigConst             number,         // IN: number to exponentiate
152     bigConst             exponent,       // IN:
153     bigConst             modulus         // IN:
154     )
155 {
156     MPA_ENTER(20, LARGEST_NUMBER_BITS);
157     BN_VAR(bnR, MAX_RSA_KEY_BITS);
158     BN_VAR(bnR2, MAX_RSA_KEY_BITS);
159     mpa_word_t              n_inv;
160     mpa_word_t              ffmCtx[mpa_fmm_context_size_in_U32(MAX_RSA_KEY_BITS)];
161 //
162     mpa_init_static_fmm_context((mpa_fmm_context_base *)ffmCtx,
163                                 BYTES_TO_CRYPT_WORDS(sizeof(ffmCtx)));
164        // Generate modular form
165     if(mpa_compute_fmm_context((const mpanum)modulus, (mpanum)bnR,
166                                (mpanum)bnR2, &n_inv, POOL) != 0)
167         FAIL(FATAL_ERROR_INTERNAL);
168     // Do exponentiation
169     mpa_exp_mod((mpanum)result, (const mpanum)number, (const mpanum)exponent,
170                 (const mpanum)modulus, (const mpanum)bnR, (const mpanum)bnR2,
171                 n_inv, POOL);
172     MPA_LEAVE();
173     return TRUE;
174 }
175 
176 //*** BnModInverse()
177 // Modular multiplicative inverse
178 LIB_EXPORT BOOL
BnModInverse(bigNum result,bigConst number,bigConst modulus)179 BnModInverse(
180     bigNum               result,
181     bigConst             number,
182     bigConst             modulus
183     )
184 {
185     BOOL            retVal;
186     MPA_ENTER(10, LARGEST_NUMBER_BITS);
187     retVal = (mpa_inv_mod((mpanum)result, (const mpanum)number,
188                           (const mpanum)modulus, POOL) == 0);
189     MPA_LEAVE();
190     return retVal;
191 }
192 #endif // TPM_ALG_RSA
193 
194 #ifdef TPM_ALG_ECC
195 
196 
197 //*** BnEccModMult()
198 // This function does a point multiply of the form R = [d]S
199 // return type: BOOL
200 //  FALSE       failure in operation; treat as result being point at infinity
201 LIB_EXPORT BOOL
BnEccModMult(bigPoint R,pointConst S,bigConst d,bigCurve E)202 BnEccModMult(
203     bigPoint             R,         // OUT: computed point
204     pointConst           S,         // IN: point to multiply by 'd'
205     bigConst             d,         // IN: scalar for [d]S
206     bigCurve             E
207     )
208 {
209     MPA_ENTER(30, MAX_ECC_KEY_BITS * 2);
210     // The point multiply in LTC seems to need a large reciprocal for
211     // intermediate results
212     POINT_VAR(result, MAX_ECC_KEY_BITS * 4);
213     BOOL                 OK;
214 //
215     (POOL);     // Avoid compiler warning
216     if(S == NULL)
217         S = CurveGetG(AccessCurveData(E));
218     OK = (ltc_ecc_mulmod((mpanum)d, (ecc_point *)S,
219                          (ecc_point *)result, (void *)CurveGetPrime(E), 1)
220           == CRYPT_OK);
221     OK = OK && !BnEqualZero(result->z);
222     if(OK)
223         BnPointCopy(R, result);
224 
225     MPA_LEAVE();
226     return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
227 }
228 
229 //*** BnEccModMult2()
230 // This function does a point multiply of the form R = [d]S + [u]Q
231 // return type: BOOL
232 //  FALSE       failure in operation; treat as result being point at infinity
233 LIB_EXPORT BOOL
BnEccModMult2(bigPoint R,pointConst S,bigConst d,pointConst Q,bigConst u,bigCurve E)234 BnEccModMult2(
235     bigPoint             R,         // OUT: computed point
236     pointConst           S,         // IN: first point (optional)
237     bigConst             d,         // IN: scalar for [d]S or [d]G
238     pointConst           Q,         // IN: second point
239     bigConst             u,         // IN: second scalar
240     bigCurve             E          // IN: curve
241     )
242 {
243     MPA_ENTER(80, MAX_ECC_KEY_BITS);
244     BOOL                 OK;
245     // The point multiply in LTC seems to need a large reciprocal for
246     // intermediate results
247     POINT_VAR(result, MAX_ECC_KEY_BITS * 4);
248 //
249     (POOL);     // Avoid compiler warning
250     if(S == NULL)
251         S = CurveGetG(AccessCurveData(E));
252 
253     OK = (ltc_ecc_mul2add((ecc_point  *)S, (mpanum)d, (ecc_point  *)Q, (mpanum)u,
254                           (ecc_point  *)result, (mpanum)CurveGetPrime(E))
255           == CRYPT_OK);
256     OK = OK && !BnEqualZero(result->z);
257 
258     if(OK)
259         BnPointCopy(R, result);
260 
261     MPA_LEAVE();
262     return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
263 }
264 
265 //*** BnEccAdd()
266 // This function does addition of two points. Since this is not implemented
267 // in LibTomCrypt() will try to trick it by doing multiply with scalar of 1.
268 // I have no idea if this will work and it's not needed unless MQV or the SM2
269 // variant is enabled.
270 // return type: BOOL
271 //  FALSE       failure in operation; treat as result being point at infinity
272 LIB_EXPORT BOOL
BnEccAdd(bigPoint R,pointConst S,pointConst Q,bigCurve E)273 BnEccAdd(
274     bigPoint             R,         // OUT: computed point
275     pointConst           S,         // IN: point to multiply by 'd'
276     pointConst           Q,         // IN: second point
277     bigCurve             E          // IN: curve
278     )
279 {
280     BN_WORD_INITIALIZED(one, 1);
281     return BnEccModMult2(R, S, one, Q, one, E);
282 }
283 
284 #endif // TPM_ALG_ECC
285 
286 #endif // MATH_LIB_LTC
287