• 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
22  *  other 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 //** Introduction
36 // The simulator code uses the canonical form whenever possible in order to make
37 // the code in Part 3 more accessible. The canonical data formats are simple and
38 // not well suited for complex big number computations. When operating on big
39 // numbers, the data format is changed for easier manipulation. The format is native
40 // words in little-endian format. As the magnitude of the number decreases, the
41 // length of the array containing the number decreases but the starting address
42 // doesn't change.
43 //
44 // The functions in this file perform simple operations on these big numbers. Only
45 // the more complex operations are passed to the underlying support library.
46 // Although the support library would have most of these functions, the interface
47 // code to convert the format for the values is greater than the size of the
48 // code to implement the functions here. So, rather than incur the overhead of
49 // conversion, they are done here.
50 //
51 // If an implementer would prefer, the underlying library can be used simply by
52 // making code substitutions here.
53 //
54 // NOTE: There is an intention to continue to augment these functions so that there
55 // would be no need to use an external big number library.
56 //
57 // Many of these functions have no error returns and will always return TRUE. This
58 // is to allow them to be used in "guarded" sequences. That is:
59 //    OK = OK || BnSomething(s);
60 // where the BnSomething() function should not be called if OK isn't true.
61 
62 //** Includes
63 #include "Tpm.h"
64 
65 // A constant value of zero as a stand in for NULL bigNum values
66 const bignum_t   BnConstZero = {1, 0, {0}};
67 
68 //** Functions
69 
70 //*** AddSame()
71 // Adds two values that are the same size. This function allows 'result' to be
72 // the same as either of the addends. This is a nice function to put into assembly
73 // because handling the carry for multi-precision stuff is not as easy in C
74 // (unless there is a REALLY smart compiler). It would be nice if there were idioms
75 // in a language that a compiler could recognize what is going on and optimize
76 // loops like this.
77 //  Return Type: int
78 //      0           no carry out
79 //      1           carry out
80 static BOOL
AddSame(crypt_uword_t * result,const crypt_uword_t * op1,const crypt_uword_t * op2,int count)81 AddSame(
82     crypt_uword_t           *result,
83     const crypt_uword_t     *op1,
84     const crypt_uword_t     *op2,
85     int                      count
86     )
87 {
88     int         carry = 0;
89     int         i;
90 
91     for(i = 0; i < count; i++)
92     {
93         crypt_uword_t        a = op1[i];
94         crypt_uword_t        sum = a + op2[i];
95         result[i] = sum + carry;
96         // generate a carry if the sum is less than either of the inputs
97         // propagate a carry if there was a carry and the sum + carry is zero
98         // do this using bit operations rather than logical operations so that
99         // the time is about the same.
100         //             propagate term      | generate term
101         carry = ((result[i] == 0) & carry) | (sum < a);
102     }
103     return carry;
104 }
105 
106 //*** CarryProp()
107 // Propagate a carry
108 static int
CarryProp(crypt_uword_t * result,const crypt_uword_t * op,int count,int carry)109 CarryProp(
110     crypt_uword_t           *result,
111     const crypt_uword_t     *op,
112     int                      count,
113     int                      carry
114     )
115 {
116     for(; count; count--)
117         carry = ((*result++ = *op++ + carry) == 0) & carry;
118     return carry;
119 }
120 
121 static void
CarryResolve(bigNum result,int stop,int carry)122 CarryResolve(
123     bigNum          result,
124     int             stop,
125     int             carry
126     )
127 {
128     if(carry)
129     {
130         pAssert((unsigned)stop < result->allocated);
131         result->d[stop++] = 1;
132     }
133     BnSetTop(result, stop);
134 }
135 
136 //*** BnAdd()
137 // This function adds two bigNum values. This function always returns TRUE.
138 LIB_EXPORT BOOL
BnAdd(bigNum result,bigConst op1,bigConst op2)139 BnAdd(
140     bigNum           result,
141     bigConst         op1,
142     bigConst         op2
143     )
144 {
145     crypt_uword_t    stop;
146     int              carry;
147     const bignum_t   *n1 = op1;
148     const bignum_t   *n2 = op2;
149 
150 //
151     if(n2->size > n1->size)
152     {
153         n1 = op2;
154         n2 = op1;
155     }
156     pAssert(result->allocated >= n1->size);
157     stop = MIN(n1->size, n2->allocated);
158     carry = (int)AddSame(result->d, n1->d, n2->d, (int)stop);
159     if(n1->size > stop)
160         carry = CarryProp(&result->d[stop], &n1->d[stop], (int)(n1->size - stop), carry);
161     CarryResolve(result, (int)n1->size, carry);
162     return TRUE;
163 }
164 
165 //*** BnAddWord()
166 // This function adds a word value to a bigNum. This function always returns TRUE.
167 LIB_EXPORT BOOL
BnAddWord(bigNum result,bigConst op,crypt_uword_t word)168 BnAddWord(
169     bigNum           result,
170     bigConst         op,
171     crypt_uword_t    word
172     )
173 {
174     int              carry;
175 //
176     carry = (result->d[0] = op->d[0] + word) < word;
177     carry = CarryProp(&result->d[1], &op->d[1], (int)(op->size - 1), carry);
178     CarryResolve(result, (int)op->size, carry);
179     return TRUE;
180 }
181 
182 //*** SubSame()
183 // This function subtracts two values that have the same size.
184 static int
SubSame(crypt_uword_t * result,const crypt_uword_t * op1,const crypt_uword_t * op2,int count)185 SubSame(
186     crypt_uword_t           *result,
187     const crypt_uword_t     *op1,
188     const crypt_uword_t     *op2,
189     int                      count
190     )
191 {
192     int                  borrow = 0;
193     int                  i;
194     for(i = 0; i < count; i++)
195     {
196         crypt_uword_t    a = op1[i];
197         crypt_uword_t    diff = a - op2[i];
198         result[i] = diff - borrow;
199         //       generate   |      propagate
200         borrow = (diff > a) | ((diff == 0) & borrow);
201     }
202     return borrow;
203 }
204 
205 //*** BorrowProp()
206 // This propagates a borrow. If borrow is true when the end
207 // of the array is reached, then it means that op2 was larger than
208 // op1 and we don't handle that case so an assert is generated.
209 // This design choice was made because our only bigNum computations
210 // are on large positive numbers (primes) or on fields.
211 // Propagate a borrow.
212 static int
BorrowProp(crypt_uword_t * result,const crypt_uword_t * op,int size,int borrow)213 BorrowProp(
214     crypt_uword_t           *result,
215     const crypt_uword_t     *op,
216     int                      size,
217     int                      borrow
218     )
219 {
220     for(; size > 0; size--)
221         borrow = ((*result++ = *op++ - borrow) == MAX_CRYPT_UWORD) && borrow;
222     return borrow;
223 }
224 
225 //*** BnSub()
226 // This function does subtraction of two bigNum values and returns result = op1 - op2
227 // when op1 is greater than op2. If op2 is greater than op1, then a fault is
228 // generated. This function always returns TRUE.
229 LIB_EXPORT BOOL
BnSub(bigNum result,bigConst op1,bigConst op2)230 BnSub(
231     bigNum           result,
232     bigConst         op1,
233     bigConst         op2
234     )
235 {
236     int             borrow;
237     int             stop = (int)MIN(op1->size, op2->allocated);
238 //
239     // Make sure that op2 is not obviously larger than op1
240     pAssert(op1->size >= op2->size);
241     borrow = SubSame(result->d, op1->d, op2->d, stop);
242     if(op1->size > (crypt_uword_t)stop)
243         borrow = BorrowProp(&result->d[stop], &op1->d[stop], (int)(op1->size - stop),
244                             borrow);
245     pAssert(!borrow);
246     BnSetTop(result, op1->size);
247     return TRUE;
248 }
249 
250 //*** BnSubWord()
251 // This function subtracts a word value from a bigNum. This function always
252 // returns TRUE.
253 LIB_EXPORT BOOL
BnSubWord(bigNum result,bigConst op,crypt_uword_t word)254 BnSubWord(
255     bigNum           result,
256     bigConst         op,
257     crypt_uword_t    word
258     )
259 {
260     int             borrow;
261 //
262     pAssert(op->size > 1 || word <= op->d[0]);
263     borrow = word > op->d[0];
264     result->d[0] = op->d[0] - word;
265     borrow = BorrowProp(&result->d[1], &op->d[1], (int)(op->size - 1), borrow);
266     pAssert(!borrow);
267     BnSetTop(result, op->size);
268     return TRUE;
269 }
270 
271 //*** BnUnsignedCmp()
272 // This function performs a comparison of op1 to op2. The compare is approximately
273 // constant time if the size of the values used in the compare is consistent
274 // across calls (from the same line in the calling code).
275 //  Return Type: int
276 //      < 0             op1 is less than op2
277 //      0               op1 is equal to op2
278 //      > 0             op1 is greater than op2
279 LIB_EXPORT int
BnUnsignedCmp(bigConst op1,bigConst op2)280 BnUnsignedCmp(
281     bigConst               op1,
282     bigConst               op2
283     )
284 {
285     int             retVal;
286     int             diff;
287     int             i;
288 //
289     pAssert((op1 != NULL) && (op2 != NULL));
290     retVal = (int)(op1->size - op2->size);
291     if(retVal == 0)
292     {
293         for(i = (int)(op1->size - 1); i >= 0; i--)
294         {
295             diff = (op1->d[i] < op2->d[i]) ? -1 : (op1->d[i] != op2->d[i]);
296             retVal = retVal == 0 ? diff : retVal;
297         }
298     }
299     else
300         retVal = (retVal < 0) ? -1 : 1;
301     return retVal;
302 }
303 
304 //*** BnUnsignedCmpWord()
305 // Compare a bigNum to a crypt_uword_t.
306 //  Return Type: int
307 //      -1              op1 is less that word
308 //      0               op1 is equal to word
309 //      1               op1 is greater than word
310 LIB_EXPORT int
BnUnsignedCmpWord(bigConst op1,crypt_uword_t word)311 BnUnsignedCmpWord(
312     bigConst             op1,
313     crypt_uword_t        word
314     )
315 {
316     if(op1->size > 1)
317         return 1;
318     else if(op1->size == 1)
319         return (op1->d[0] < word) ? -1 : (op1->d[0] > word);
320     else // op1 is zero
321         // equal if word is zero
322         return (word == 0) ? 0 : -1;
323 }
324 
325 //*** BnModWord()
326 // This function does modular division of a big number when the modulus is a
327 // word value.
328 LIB_EXPORT crypt_word_t
BnModWord(bigConst numerator,crypt_word_t modulus)329 BnModWord(
330     bigConst         numerator,
331     crypt_word_t     modulus
332     )
333 {
334     BN_MAX(remainder);
335     BN_VAR(mod, RADIX_BITS);
336 //
337     mod->d[0] = modulus;
338     mod->size = (modulus != 0);
339     BnDiv(NULL, remainder, numerator, mod);
340     return remainder->d[0];
341 }
342 
343 //*** Msb()
344 // This function returns the bit number of the most significant bit of a
345 // crypt_uword_t. The number for the least significant bit of any bigNum value is 0.
346 // The maximum return value is RADIX_BITS - 1,
347 //  Return Type: int
348 //      -1              the word was zero
349 //      n               the bit number of the most significant bit in the word
350 LIB_EXPORT int
Msb(crypt_uword_t word)351 Msb(
352     crypt_uword_t           word
353     )
354 {
355     int             retVal = -1;
356 //
357 #if RADIX_BITS == 64
358     if(word & 0xffffffff00000000) { retVal += 32; word >>= 32; }
359 #endif
360     if(word & 0xffff0000) { retVal += 16; word >>= 16; }
361     if(word & 0x0000ff00) { retVal += 8; word >>= 8; }
362     if(word & 0x000000f0) { retVal += 4; word >>= 4; }
363     if(word & 0x0000000c) { retVal += 2; word >>= 2; }
364     if(word & 0x00000002) { retVal += 1; word >>= 1; }
365     return retVal + (int)word;
366 }
367 
368 //*** BnMsb()
369 // This function returns the number of the MSb of a bigNum value.
370 //  Return Type: int
371 //      -1              the word was zero or 'bn' was NULL
372 //      n               the bit number of the most significant bit in the word
373 LIB_EXPORT int
BnMsb(bigConst bn)374 BnMsb(
375     bigConst            bn
376     )
377 {
378     // If the value is NULL, or the size is zero then treat as zero and return -1
379     if(bn != NULL && bn->size > 0)
380     {
381         int         retVal = Msb(bn->d[bn->size - 1]);
382         retVal += (int)(bn->size - 1) * RADIX_BITS;
383         return retVal;
384     }
385     else
386         return -1;
387 }
388 
389 //*** BnSizeInBits()
390 // This function returns the number of bits required to hold a number. It is one
391 // greater than the Msb.
392 //
393 LIB_EXPORT unsigned
BnSizeInBits(bigConst n)394 BnSizeInBits(
395     bigConst                 n
396     )
397 {
398     int     bits = BnMsb(n) + 1;
399 //
400     return bits < 0? 0 : (unsigned)bits;
401 }
402 
403 //*** BnSetWord()
404 // Change the value of a bignum_t to a word value.
405 LIB_EXPORT bigNum
BnSetWord(bigNum n,crypt_uword_t w)406 BnSetWord(
407     bigNum               n,
408     crypt_uword_t        w
409     )
410 {
411     if(n != NULL)
412     {
413         pAssert(n->allocated > 1);
414         n->d[0] = w;
415         BnSetTop(n, (w != 0) ? 1 : 0);
416     }
417     return n;
418 }
419 
420 //*** BnSetBit()
421 // This function will SET a bit in a bigNum. Bit 0 is the least-significant bit in
422 // the 0th digit_t. The function always return TRUE
423 LIB_EXPORT BOOL
BnSetBit(bigNum bn,unsigned int bitNum)424 BnSetBit(
425     bigNum           bn,        // IN/OUT: big number to modify
426     unsigned int     bitNum     // IN: Bit number to SET
427     )
428 {
429     crypt_uword_t            offset = bitNum / RADIX_BITS;
430     pAssert(bn->allocated * RADIX_BITS >= bitNum);
431     // Grow the number if necessary to set the bit.
432     while(bn->size <= offset)
433         bn->d[bn->size++] = 0;
434     bn->d[offset] |= ((crypt_uword_t)1 << RADIX_MOD(bitNum));
435     return TRUE;
436 }
437 
438 //*** BnTestBit()
439 // This function is used to check to see if a bit is SET in a bignum_t. The 0th bit
440 // is the LSb of d[0].
441 //  Return Type: BOOL
442 //      TRUE(1)         the bit is set
443 //      FALSE(0)        the bit is not set or the number is out of range
444 LIB_EXPORT BOOL
BnTestBit(bigNum bn,unsigned int bitNum)445 BnTestBit(
446     bigNum               bn,        // IN: number to check
447     unsigned int         bitNum     // IN: bit to test
448     )
449 {
450     crypt_uword_t         offset = RADIX_DIV(bitNum);
451 //
452     if(bn->size > offset)
453         return ((bn->d[offset] & (((crypt_uword_t)1) << RADIX_MOD(bitNum))) != 0);
454     else
455         return FALSE;
456 }
457 
458 //***BnMaskBits()
459 // This function is used to mask off high order bits of a big number.
460 // The returned value will have no more than 'maskBit' bits
461 // set.
462 // Note: There is a requirement that unused words of a bignum_t are set to zero.
463 //  Return Type: BOOL
464 //      TRUE(1)         result masked
465 //      FALSE(0)        the input was not as large as the mask
466 LIB_EXPORT BOOL
BnMaskBits(bigNum bn,crypt_uword_t maskBit)467 BnMaskBits(
468     bigNum           bn,        // IN/OUT: number to mask
469     crypt_uword_t    maskBit    // IN: the bit number for the mask.
470     )
471 {
472     crypt_uword_t    finalSize;
473     BOOL             retVal;
474 
475     finalSize = BITS_TO_CRYPT_WORDS(maskBit);
476     retVal = (finalSize <= bn->allocated);
477     if(retVal && (finalSize > 0))
478     {
479         crypt_uword_t   mask;
480         mask = ~((crypt_uword_t)0) >> RADIX_MOD(maskBit);
481         bn->d[finalSize - 1] &= mask;
482     }
483     BnSetTop(bn, finalSize);
484     return retVal;
485 }
486 
487 //*** BnShiftRight()
488 // This function will shift a bigNum to the right by the shiftAmount.
489 // This function always returns TRUE.
490 LIB_EXPORT BOOL
BnShiftRight(bigNum result,bigConst toShift,uint32_t shiftAmount)491 BnShiftRight(
492     bigNum           result,
493     bigConst         toShift,
494     uint32_t         shiftAmount
495     )
496 {
497     uint32_t         offset = (shiftAmount >> RADIX_LOG2);
498     uint32_t         i;
499     uint32_t         shiftIn;
500     crypt_uword_t    finalSize;
501 //
502     shiftAmount = shiftAmount & RADIX_MASK;
503     shiftIn = RADIX_BITS - shiftAmount;
504 
505     // The end size is toShift->size - offset less one additional
506     // word if the shiftAmount would make the upper word == 0
507     if(toShift->size > offset)
508     {
509         finalSize = toShift->size - offset;
510         finalSize -= (toShift->d[toShift->size - 1] >> shiftAmount) == 0 ? 1 : 0;
511     }
512     else
513         finalSize = 0;
514 
515     pAssert(finalSize <= result->allocated);
516     if(finalSize != 0)
517     {
518         for(i = 0; i < finalSize; i++)
519         {
520             result->d[i] = (toShift->d[i + offset] >> shiftAmount)
521                 | (toShift->d[i + offset + 1] << shiftIn);
522         }
523         if(offset == 0)
524             result->d[i] = toShift->d[i] >> shiftAmount;
525     }
526     BnSetTop(result, finalSize);
527     return TRUE;
528 }
529 
530 //*** BnGetRandomBits()
531 // This function gets random bits for use in various places. To make sure that the
532 // number is generated in a portable format, it is created as a TPM2B and then
533 // converted to the internal format.
534 //
535 // One consequence of the generation scheme is that, if the number of bits requested
536 // is not a multiple of 8, then the high-order bits are set to zero. This would come
537 // into play when generating a 521-bit ECC key. A 66-byte (528-bit) value is
538 // generated an the high order 7 bits are masked off (CLEAR).
539 //  Return Type: BOOL
540 //      TRUE(1)         success
541 //      FALSE(0)        failure
542 LIB_EXPORT BOOL
BnGetRandomBits(bigNum n,size_t bits,RAND_STATE * rand)543 BnGetRandomBits(
544     bigNum           n,
545     size_t           bits,
546     RAND_STATE      *rand
547 )
548 {
549     // Since this could be used for ECC key generation using the extra bits method,
550     // make sure that the value is large enough
551     TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8);
552     TPM2B_LARGEST    large;
553 //
554     large.b.size = (UINT16)BITS_TO_BYTES(bits);
555     if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size)
556     {
557         if(BnFrom2B(n, &large.b) != NULL)
558         {
559             if(BnMaskBits(n, (crypt_uword_t)bits))
560                 return TRUE;
561         }
562     }
563     return FALSE;
564 }
565 
566 //*** BnGenerateRandomInRange()
567 // This function is used to generate a random number r in the range 1 <= r < limit.
568 // The function gets a random number of bits that is the size of limit. There is some
569 // some probability that the returned number is going to be greater than or equal
570 // to the limit. If it is, try again. There is no more than 50% chance that the
571 // next number is also greater, so try again. We keep trying until we get a
572 // value that meets the criteria. Since limit is very often a number with a LOT of
573 // high order ones, this rarely would need a second try.
574 //  Return Type: BOOL
575 //      TRUE(1)         success
576 //      FALSE(0)        failure ('limit' is too small)
577 LIB_EXPORT BOOL
BnGenerateRandomInRange(bigNum dest,bigConst limit,RAND_STATE * rand)578 BnGenerateRandomInRange(
579     bigNum           dest,
580     bigConst         limit,
581     RAND_STATE      *rand
582     )
583 {
584     size_t   bits = BnSizeInBits(limit);
585 //
586     if(bits < 2)
587     {
588         BnSetWord(dest, 0);
589         return FALSE;
590     }
591     else
592     {
593         while(BnGetRandomBits(dest, bits, rand)
594               && (BnEqualZero(dest) || (BnUnsignedCmp(dest, limit) >= 0)));
595     }
596     return !g_inFailureMode;
597 }