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