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