• 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 //
37 // This file contains implementation of the math functions that are performed
38 // with canonical integers in byte buffers. The canonical integer is
39 // big-endian bytes.
40 //
41 #include "Tpm.h"
42 
43 //** Functions
44 
45 //*** UnsignedCmpB
46 // This function compare two unsigned values. The values are byte-aligned,
47 // big-endian numbers (e.g, a hash).
48 //  Return Type: int
49 //      1          if (a > b)
50 //      0          if (a = b)
51 //      -1         if (a < b)
52 LIB_EXPORT int
UnsignedCompareB(UINT32 aSize,const BYTE * a,UINT32 bSize,const BYTE * b)53 UnsignedCompareB(
54     UINT32           aSize,         // IN: size of a
55     const BYTE      *a,             // IN: a
56     UINT32           bSize,         // IN: size of b
57     const BYTE      *b              // IN: b
58     )
59 {
60     UINT32             i;
61     if(aSize > bSize)
62         return 1;
63     else if(aSize < bSize)
64         return -1;
65     else
66     {
67         for(i = 0; i < aSize; i++)
68         {
69             if(a[i] != b[i])
70                 return (a[i] > b[i]) ? 1 : -1;
71         }
72     }
73     return 0;
74 }
75 
76 //***SignedCompareB()
77 // Compare two signed integers:
78 //  Return Type: int
79 //      1         if a > b
80 //      0         if a = b
81 //      -1        if a < b
82 int
SignedCompareB(const UINT32 aSize,const BYTE * a,const UINT32 bSize,const BYTE * b)83 SignedCompareB(
84     const UINT32     aSize,         // IN: size of a
85     const BYTE      *a,             // IN: a buffer
86     const UINT32     bSize,         // IN: size of b
87     const BYTE      *b              // IN: b buffer
88     )
89 {
90     int      signA, signB;       // sign of a and b
91 
92     // For positive or 0, sign_a is 1
93     // for negative, sign_a is 0
94     signA = ((a[0] & 0x80) == 0) ? 1 : 0;
95 
96     // For positive or 0, sign_b is 1
97     // for negative, sign_b is 0
98     signB = ((b[0] & 0x80) == 0) ? 1 : 0;
99 
100     if(signA != signB)
101     {
102         return signA - signB;
103     }
104     if(signA == 1)
105         // do unsigned compare function
106         return UnsignedCompareB(aSize, a, bSize, b);
107     else
108         // do unsigned compare the other way
109         return 0 - UnsignedCompareB(aSize, a, bSize, b);
110 }
111 
112 //*** ModExpB
113 // This function is used to do modular exponentiation in support of RSA.
114 // The most typical uses are: 'c' = 'm'^'e' mod 'n' (RSA encrypt) and
115 // 'm' = 'c'^'d' mod 'n' (RSA decrypt).  When doing decryption, the 'e' parameter
116 // of the function will contain the private exponent 'd' instead of the public
117 // exponent 'e'.
118 //
119 // If the results will not fit in the provided buffer,
120 // an error is returned (CRYPT_ERROR_UNDERFLOW). If the results is smaller
121 // than the buffer, the results is de-normalized.
122 //
123 // This version is intended for use with RSA and requires that 'm' be
124 // less than 'n'.
125 //
126 //  Return Type: TPM_RC
127 //      TPM_RC_SIZE         number to exponentiate is larger than the modulus
128 //      TPM_RC_NO_RESULT    result will not fit into the provided buffer
129 //
130 TPM_RC
ModExpB(UINT32 cSize,BYTE * c,const UINT32 mSize,const BYTE * m,const UINT32 eSize,const BYTE * e,const UINT32 nSize,const BYTE * n)131 ModExpB(
132     UINT32           cSize,         // IN: the size of the output buffer. It will
133                                     //     need to be the same size as the modulus
134     BYTE            *c,             // OUT: the buffer to receive the results
135                                     //     (c->size must be set to the maximum size
136                                     //     for the returned value)
137     const UINT32     mSize,
138     const BYTE      *m,             // IN: number to exponentiate
139     const UINT32     eSize,
140     const BYTE      *e,             // IN: power
141     const UINT32     nSize,
142     const BYTE      *n              // IN: modulus
143     )
144 {
145     BN_MAX(bnC);
146     BN_MAX(bnM);
147     BN_MAX(bnE);
148     BN_MAX(bnN);
149     NUMBYTES         tSize = (NUMBYTES)nSize;
150     TPM_RC           retVal = TPM_RC_SUCCESS;
151 
152     // Convert input parameters
153     BnFromBytes(bnM, m, (NUMBYTES)mSize);
154     BnFromBytes(bnE, e, (NUMBYTES)eSize);
155     BnFromBytes(bnN, n, (NUMBYTES)nSize);
156 
157 
158     // Make sure that the output is big enough to hold the result
159     // and that 'm' is less than 'n' (the modulus)
160     if(cSize < nSize)
161         ERROR_RETURN(TPM_RC_NO_RESULT);
162     if(BnUnsignedCmp(bnM, bnN) >= 0)
163         ERROR_RETURN(TPM_RC_SIZE);
164     BnModExp(bnC, bnM, bnE, bnN);
165     BnToBytes(bnC, c, &tSize);
166 Exit:
167     return retVal;
168 }
169 
170 //*** DivideB()
171 // Divide an integer ('n') by an integer ('d') producing a quotient ('q') and
172 // a remainder ('r'). If 'q' or 'r' is not needed, then the pointer to them
173 // may be set to NULL.
174 //
175 //  Return Type: TPM_RC
176 //      TPM_RC_NO_RESULT         'q' or 'r' is too small to receive the result
177 //
178 LIB_EXPORT TPM_RC
DivideB(const TPM2B * n,const TPM2B * d,TPM2B * q,TPM2B * r)179 DivideB(
180     const TPM2B     *n,             // IN: numerator
181     const TPM2B     *d,             // IN: denominator
182     TPM2B           *q,             // OUT: quotient
183     TPM2B           *r              // OUT: remainder
184     )
185 {
186     BN_MAX_INITIALIZED(bnN, n);
187     BN_MAX_INITIALIZED(bnD, d);
188     BN_MAX(bnQ);
189     BN_MAX(bnR);
190 //
191     // Do divide with converted values
192     BnDiv(bnQ, bnR, bnN, bnD);
193 
194     // Convert the BIGNUM result back to 2B format using the size of the original
195     // number
196     if(q != NULL)
197         if(!BnTo2B(bnQ, q, q->size))
198             return TPM_RC_NO_RESULT;
199     if(r != NULL)
200         if(!BnTo2B(bnR, r, r->size))
201             return TPM_RC_NO_RESULT;
202     return TPM_RC_SUCCESS;
203 }
204 
205 //*** AdjustNumberB()
206 // Remove/add leading zeros from a number in a TPM2B. Will try to make the number
207 // by adding or removing leading zeros. If the number is larger than the requested
208 // size, it will make the number as small as possible. Setting 'requestedSize' to
209 // zero is equivalent to requesting that the number be normalized.
210 UINT16
AdjustNumberB(TPM2B * num,UINT16 requestedSize)211 AdjustNumberB(
212     TPM2B           *num,
213     UINT16           requestedSize
214     )
215 {
216     BYTE            *from;
217     UINT16           i;
218     // See if number is already the requested size
219     if(num->size == requestedSize)
220         return requestedSize;
221     from = num->buffer;
222     if (num->size > requestedSize)
223     {
224     // This is a request to shift the number to the left (remove leading zeros)
225         // Find the first non-zero byte. Don't look past the point where removing
226         // more zeros would make the number smaller than requested, and don't throw
227         // away any significant digits.
228         for(i = num->size; *from == 0 && i > requestedSize; from++, i--);
229         if(i < num->size)
230         {
231             num->size = i;
232             MemoryCopy(num->buffer, from, i);
233         }
234     }
235     // This is a request to shift the number to the right (add leading zeros)
236     else
237     {
238         MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size);
239         MemorySet(num->buffer, 0, requestedSize- num->size);
240         num->size = requestedSize;
241     }
242     return num->size;
243 }
244 
245 //*** ShiftLeft()
246 // This function shifts a byte buffer (a TPM2B) one byte to the left. That is,
247 // the most significant bit of the most significant byte is lost.
248 TPM2B *
ShiftLeft(TPM2B * value)249 ShiftLeft(
250     TPM2B       *value          // IN/OUT: value to shift and shifted value out
251 )
252 {
253     UINT16       count = value->size;
254     BYTE        *buffer = value->buffer;
255     if(count > 0)
256     {
257         for(count -= 1; count > 0; buffer++, count--)
258         {
259             buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0);
260         }
261         *buffer <<= 1;
262     }
263     return value;
264 }
265 
266