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 wolfcrypt library to execute
40 // the operations. There is a difference between the internal format and the
41 // wolfcrypt format. To call the wolfcrypt function, a mp_int structure is created
42 // for each passed variable. We define USE_FAST_MATH wolfcrypt option, which allocates
43 // mp_int on the stack. We must copy each word to the new structure, and set the used
44 // size.
45 //
46 // Not using USE_FAST_MATH would allow for a simple pointer swap for the big integer
47 // buffer 'd', however wolfcrypt expects to manage this memory, and will swap out
48 // the pointer to and from temporary variables and free the reference underneath us.
49 // Using USE_FAST_MATH also instructs wolfcrypt to use the stack for all these
50 // intermediate variables
51
52
53 //** Includes and Defines
54 #include "Tpm.h"
55
56 #ifdef MATH_LIB_WOLF
57 #include "BnConvert_fp.h"
58 #include "TpmToWolfMath_fp.h"
59
60 #define WOLF_HALF_RADIX (RADIX_BITS == 64 && !defined(FP_64BIT))
61
62 //** Functions
63
64 //*** BnFromWolf()
65 // This function converts a wolfcrypt mp_int to a TPM bignum. In this implementation
66 // it is assumed that wolfcrypt used the same format for a big number as does the
67 // TPM -- an array of native-endian words in little-endian order.
68 void
BnFromWolf(bigNum bn,mp_int * wolfBn)69 BnFromWolf(
70 bigNum bn,
71 mp_int *wolfBn
72 )
73 {
74 if(bn != NULL)
75 {
76 int i;
77 #if WOLF_HALF_RADIX
78 pAssert((unsigned)wolfBn->used <= 2 * BnGetAllocated(bn));
79 #else
80 pAssert((unsigned)wolfBn->used <= BnGetAllocated(bn));
81 #endif
82 for (i = 0; i < wolfBn->used; i++)
83 {
84 #if WOLF_HALF_RADIX
85 if (i & 1)
86 bn->d[i/2] |= (crypt_uword_t)wolfBn->dp[i] << 32;
87 else
88 bn->d[i/2] = wolfBn->dp[i];
89 #else
90 bn->d[i] = wolfBn->dp[i];
91 #endif
92 }
93
94 #if WOLF_HALF_RADIX
95 BnSetTop(bn, (wolfBn->used + 1)/2);
96 #else
97 BnSetTop(bn, wolfBn->used);
98 #endif
99 }
100 }
101
102 //*** BnToWolf()
103 // This function converts a TPM bignum to a wolfcrypt mp_init, and has the same
104 // assumptions as made by BnFromWolf()
105 void
BnToWolf(mp_int * toInit,bigConst initializer)106 BnToWolf(
107 mp_int *toInit,
108 bigConst initializer
109 )
110 {
111 uint32_t i;
112 if (toInit != NULL && initializer != NULL)
113 {
114 for (i = 0; i < initializer->size; i++)
115 {
116 #if WOLF_HALF_RADIX
117 toInit->dp[2 * i] = (fp_digit)initializer->d[i];
118 toInit->dp[2 * i + 1] = (fp_digit)(initializer->d[i] >> 32);
119 #else
120 toInit->dp[i] = initializer->d[i];
121 #endif
122 }
123
124 #if WOLF_HALF_RADIX
125 toInit->used = (int)initializer->size * 2;
126 if (toInit->dp[toInit->used - 1] == 0 && toInit->dp[toInit->used - 2] != 0)
127 --toInit->used;
128 #else
129 toInit->used = (int)initializer->size;
130 #endif
131 toInit->sign = 0;
132 }
133 }
134
135 //*** MpInitialize()
136 // This function initializes an wolfcrypt mp_int.
137 mp_int *
MpInitialize(mp_int * toInit)138 MpInitialize(
139 mp_int *toInit
140 )
141 {
142 mp_init( toInit );
143 return toInit;
144 }
145
146 #if LIBRARY_COMPATIBILITY_CHECK
147 //** MathLibraryCompatibililtyCheck()
148 // This function is only used during development to make sure that the library
149 // that is being referenced is using the same size of data structures as the TPM.
150 BOOL
MathLibraryCompatibilityCheck(void)151 MathLibraryCompatibilityCheck(
152 void
153 )
154 {
155 BN_VAR(tpmTemp, 64 * 8); // allocate some space for a test value
156 crypt_uword_t i;
157 TPM2B_TYPE(TEST, 16);
158 TPM2B_TEST test = {{16, {0x0F, 0x0E, 0x0D, 0x0C,
159 0x0B, 0x0A, 0x09, 0x08,
160 0x07, 0x06, 0x05, 0x04,
161 0x03, 0x02, 0x01, 0x00}}};
162 // Convert the test TPM2B to a bigNum
163 BnFrom2B(tpmTemp, &test.b);
164 MP_INITIALIZED(wolfTemp, tpmTemp);
165 (wolfTemp); // compiler warning
166 // Make sure the values are consistent
167 VERIFY(wolfTemp->used * sizeof(fp_digit) == (int)tpmTemp->size * sizeof(crypt_uword_t));
168 for(i = 0; i < tpmTemp->size; i++)
169 VERIFY(((crypt_uword_t*)wolfTemp->dp)[i] == tpmTemp->d[i]);
170 return 1;
171 Error:
172 return 0;
173 }
174 #endif
175
176 //*** BnModMult()
177 // Does multiply and divide returning the remainder of the divide.
178 LIB_EXPORT BOOL
BnModMult(bigNum result,bigConst op1,bigConst op2,bigConst modulus)179 BnModMult(
180 bigNum result,
181 bigConst op1,
182 bigConst op2,
183 bigConst modulus
184 )
185 {
186 WOLF_ENTER();
187 BOOL OK;
188 MP_INITIALIZED(bnOp1, op1);
189 MP_INITIALIZED(bnOp2, op2);
190 MP_INITIALIZED(bnTemp, NULL);
191 BN_VAR(temp, LARGEST_NUMBER_BITS * 2);
192
193 pAssert(BnGetAllocated(result) >= BnGetSize(modulus));
194
195 OK = (mp_mul( bnOp1, bnOp2, bnTemp ) == MP_OKAY);
196 if(OK)
197 {
198 BnFromWolf(temp, bnTemp);
199 OK = BnDiv(NULL, result, temp, modulus);
200 }
201
202 WOLF_LEAVE();
203 return OK;
204 }
205
206 //*** BnMult()
207 // Multiplies two numbers
208 LIB_EXPORT BOOL
BnMult(bigNum result,bigConst multiplicand,bigConst multiplier)209 BnMult(
210 bigNum result,
211 bigConst multiplicand,
212 bigConst multiplier
213 )
214 {
215 WOLF_ENTER();
216 BOOL OK;
217 MP_INITIALIZED(bnTemp, NULL);
218 MP_INITIALIZED(bnA, multiplicand);
219 MP_INITIALIZED(bnB, multiplier);
220
221 pAssert(result->allocated >=
222 (BITS_TO_CRYPT_WORDS(BnSizeInBits(multiplicand)
223 + BnSizeInBits(multiplier))));
224
225 OK = (mp_mul( bnA, bnB, bnTemp ) == MP_OKAY);
226 if(OK)
227 {
228 BnFromWolf(result, bnTemp);
229 }
230
231 WOLF_LEAVE();
232 return OK;
233 }
234
235 //*** BnDiv()
236 // This function divides two bigNum values. The function returns FALSE if
237 // there is an error in the operation.
238 LIB_EXPORT BOOL
BnDiv(bigNum quotient,bigNum remainder,bigConst dividend,bigConst divisor)239 BnDiv(
240 bigNum quotient,
241 bigNum remainder,
242 bigConst dividend,
243 bigConst divisor
244 )
245 {
246 WOLF_ENTER();
247 BOOL OK;
248 MP_INITIALIZED(bnQ, quotient);
249 MP_INITIALIZED(bnR, remainder);
250 MP_INITIALIZED(bnDend, dividend);
251 MP_INITIALIZED(bnSor, divisor);
252 pAssert(!BnEqualZero(divisor));
253 if(BnGetSize(dividend) < BnGetSize(divisor))
254 {
255 if(quotient)
256 BnSetWord(quotient, 0);
257 if(remainder)
258 BnCopy(remainder, dividend);
259 OK = TRUE;
260 }
261 else
262 {
263 pAssert((quotient == NULL)
264 || (quotient->allocated >= (unsigned)(dividend->size
265 - divisor->size)));
266 pAssert((remainder == NULL)
267 || (remainder->allocated >= divisor->size));
268 OK = (mp_div(bnDend , bnSor, bnQ, bnR) == MP_OKAY);
269 if(OK)
270 {
271 BnFromWolf(quotient, bnQ);
272 BnFromWolf(remainder, bnR);
273 }
274 }
275
276 WOLF_LEAVE();
277 return OK;
278 }
279
280 #if ALG_RSA
281 //*** BnGcd()
282 // Get the greatest common divisor of two numbers
283 LIB_EXPORT BOOL
BnGcd(bigNum gcd,bigConst number1,bigConst number2)284 BnGcd(
285 bigNum gcd, // OUT: the common divisor
286 bigConst number1, // IN:
287 bigConst number2 // IN:
288 )
289 {
290 WOLF_ENTER();
291 BOOL OK;
292 MP_INITIALIZED(bnGcd, gcd);
293 MP_INITIALIZED(bn1, number1);
294 MP_INITIALIZED(bn2, number2);
295 pAssert(gcd != NULL);
296 OK = (mp_gcd( bn1, bn2, bnGcd ) == MP_OKAY);
297 if(OK)
298 {
299 BnFromWolf(gcd, bnGcd);
300 }
301 WOLF_LEAVE();
302 return OK;
303 }
304
305 //***BnModExp()
306 // Do modular exponentiation using bigNum values. The conversion from a mp_int to
307 // a bigNum is trivial as they are based on the same structure
308 LIB_EXPORT BOOL
BnModExp(bigNum result,bigConst number,bigConst exponent,bigConst modulus)309 BnModExp(
310 bigNum result, // OUT: the result
311 bigConst number, // IN: number to exponentiate
312 bigConst exponent, // IN:
313 bigConst modulus // IN:
314 )
315 {
316 WOLF_ENTER();
317 BOOL OK;
318 MP_INITIALIZED(bnResult, result);
319 MP_INITIALIZED(bnN, number);
320 MP_INITIALIZED(bnE, exponent);
321 MP_INITIALIZED(bnM, modulus);
322 OK = (mp_exptmod( bnN, bnE, bnM, bnResult ) == MP_OKAY);
323 if(OK)
324 {
325 BnFromWolf(result, bnResult);
326 }
327
328 WOLF_LEAVE();
329 return OK;
330 }
331
332 //*** BnModInverse()
333 // Modular multiplicative inverse
334 LIB_EXPORT BOOL
BnModInverse(bigNum result,bigConst number,bigConst modulus)335 BnModInverse(
336 bigNum result,
337 bigConst number,
338 bigConst modulus
339 )
340 {
341 WOLF_ENTER();
342 BOOL OK;
343 MP_INITIALIZED(bnResult, result);
344 MP_INITIALIZED(bnN, number);
345 MP_INITIALIZED(bnM, modulus);
346
347 OK = (mp_invmod(bnN, bnM, bnResult) == MP_OKAY);
348 if(OK)
349 {
350 BnFromWolf(result, bnResult);
351 }
352
353 WOLF_LEAVE();
354 return OK;
355 }
356 #endif // TPM_ALG_RSA
357
358 #if ALG_ECC
359
360 //*** PointFromWolf()
361 // Function to copy the point result from a wolf ecc_point to a bigNum
362 void
PointFromWolf(bigPoint pOut,ecc_point * pIn)363 PointFromWolf(
364 bigPoint pOut, // OUT: resulting point
365 ecc_point *pIn // IN: the point to return
366 )
367 {
368 BnFromWolf(pOut->x, pIn->x);
369 BnFromWolf(pOut->y, pIn->y);
370 BnFromWolf(pOut->z, pIn->z);
371 }
372
373 //*** PointToWolf()
374 // Function to copy the point result from a bigNum to a wolf ecc_point
375 void
PointToWolf(ecc_point * pOut,pointConst pIn)376 PointToWolf(
377 ecc_point *pOut, // OUT: resulting point
378 pointConst pIn // IN: the point to return
379 )
380 {
381 BnToWolf(pOut->x, pIn->x);
382 BnToWolf(pOut->y, pIn->y);
383 BnToWolf(pOut->z, pIn->z);
384 }
385
386 //*** EcPointInitialized()
387 // Allocate and initialize a point.
388 static ecc_point *
EcPointInitialized(pointConst initializer)389 EcPointInitialized(
390 pointConst initializer
391 )
392 {
393 ecc_point *P;
394
395 P = wc_ecc_new_point();
396 pAssert(P != NULL);
397 // mp_int x,y,z are stack allocated.
398 // initializer is not required
399 if (P != NULL && initializer != NULL)
400 {
401 PointToWolf( P, initializer );
402 }
403
404 return P;
405 }
406
407 //*** BnEccModMult()
408 // This function does a point multiply of the form R = [d]S
409 // return type: BOOL
410 // FALSE failure in operation; treat as result being point at infinity
411 LIB_EXPORT BOOL
BnEccModMult(bigPoint R,pointConst S,bigConst d,bigCurve E)412 BnEccModMult(
413 bigPoint R, // OUT: computed point
414 pointConst S, // IN: point to multiply by 'd' (optional)
415 bigConst d, // IN: scalar for [d]S
416 bigCurve E
417 )
418 {
419 WOLF_ENTER();
420 BOOL OK;
421 MP_INITIALIZED(bnD, d);
422 MP_INITIALIZED(bnPrime, CurveGetPrime(E));
423 POINT_CREATE(pS, NULL);
424 POINT_CREATE(pR, NULL);
425
426 if(S == NULL)
427 S = CurveGetG(AccessCurveData(E));
428
429 PointToWolf(pS, S);
430
431 OK = (wc_ecc_mulmod(bnD, pS, pR, NULL, bnPrime, 1 ) == MP_OKAY);
432 if(OK)
433 {
434 PointFromWolf(R, pR);
435 }
436
437 POINT_DELETE(pR);
438 POINT_DELETE(pS);
439
440 WOLF_LEAVE();
441 return !BnEqualZero(R->z);
442 }
443
444 //*** BnEccModMult2()
445 // This function does a point multiply of the form R = [d]G + [u]Q
446 // return type: BOOL
447 // FALSE failure in operation; treat as result being point at infinity
448 LIB_EXPORT BOOL
BnEccModMult2(bigPoint R,pointConst S,bigConst d,pointConst Q,bigConst u,bigCurve E)449 BnEccModMult2(
450 bigPoint R, // OUT: computed point
451 pointConst S, // IN: optional point
452 bigConst d, // IN: scalar for [d]S or [d]G
453 pointConst Q, // IN: second point
454 bigConst u, // IN: second scalar
455 bigCurve E // IN: curve
456 )
457 {
458 WOLF_ENTER();
459 BOOL OK;
460 POINT_CREATE(pR, NULL);
461 POINT_CREATE(pS, NULL);
462 POINT_CREATE(pQ, Q);
463 MP_INITIALIZED(bnD, d);
464 MP_INITIALIZED(bnU, u);
465 MP_INITIALIZED(bnPrime, CurveGetPrime(E));
466 MP_INITIALIZED(bnA, CurveGet_a(E));
467
468 if(S == NULL)
469 S = CurveGetG(AccessCurveData(E));
470 PointToWolf( pS, S );
471
472 OK = (ecc_mul2add(pS, bnD, pQ, bnU, pR, bnA, bnPrime, NULL) == MP_OKAY);
473 if(OK)
474 {
475 PointFromWolf(R, pR);
476 }
477
478 POINT_DELETE(pS);
479 POINT_DELETE(pQ);
480 POINT_DELETE(pR);
481
482 WOLF_LEAVE();
483 return !BnEqualZero(R->z);
484 }
485
486 //** BnEccAdd()
487 // This function does addition of two points.
488 // return type: BOOL
489 // FALSE failure in operation; treat as result being point at infinity
490 LIB_EXPORT BOOL
BnEccAdd(bigPoint R,pointConst S,pointConst Q,bigCurve E)491 BnEccAdd(
492 bigPoint R, // OUT: computed point
493 pointConst S, // IN: point to multiply by 'd'
494 pointConst Q, // IN: second point
495 bigCurve E // IN: curve
496 )
497 {
498 WOLF_ENTER();
499 BOOL OK;
500 mp_digit mp;
501 POINT_CREATE(pR, NULL);
502 POINT_CREATE(pS, S);
503 POINT_CREATE(pQ, Q);
504 MP_INITIALIZED(bnA, CurveGet_a(E));
505 MP_INITIALIZED(bnMod, CurveGetPrime(E));
506 //
507 OK = (mp_montgomery_setup(bnMod, &mp) == MP_OKAY);
508 OK = OK && (ecc_projective_add_point(pS, pQ, pR, bnA, bnMod, mp ) == MP_OKAY);
509 if(OK)
510 {
511 PointFromWolf(R, pR);
512 }
513
514 POINT_DELETE(pS);
515 POINT_DELETE(pQ);
516 POINT_DELETE(pR);
517
518 WOLF_LEAVE();
519 return !BnEqualZero(R->z);
520 }
521
522 #endif // TPM_ALG_ECC
523
524 #endif // MATH_LIB_WOLF