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 ST MPA library or the
40 // LibTomCrypt library to execute the operations. Since the TPM internal big number
41 // format is identical to the MPA format, no reformatting is required.
42
43 //** Includes
44 #include "Tpm.h"
45
46 #ifdef MATH_LIB_LTC
47
48 #if defined ECC_NIST_P256 && ECC_NIST_P256 == YES && ECC_CURVE_COUNT > 1
49 #error "LibTomCrypt only supports P256"
50 #endif
51
52 //** Functions
53
54 //*** BnModMult()
55 // Does multiply and divide returning the remainder of the divide.
56 LIB_EXPORT BOOL
BnModMult(bigNum result,bigConst op1,bigConst op2,bigConst modulus)57 BnModMult(
58 bigNum result,
59 bigConst op1,
60 bigConst op2,
61 bigConst modulus
62 )
63 {
64 BN_VAR(temp, LARGEST_NUMBER_BITS * 2);
65 // mpa_mul does not allocate from the pool if the result is not the same as
66 // op1 or op2. since this is assured by the stack allocation of 'temp', the
67 // pool pointer can be NULL
68 pAssert(BnGetAllocated(result) >= BnGetSize(modulus));
69 mpa_mul((mpanum)temp, (const mpanum)op1, (const mpanum)op2,
70 NULL);
71 return BnDiv(NULL, result, temp, modulus);
72 }
73
74 //*** BnMult()
75 // Multiplies two numbers
76 LIB_EXPORT BOOL
BnMult(bigNum result,bigConst multiplicand,bigConst multiplier)77 BnMult(
78 bigNum result,
79 bigConst multiplicand,
80 bigConst multiplier
81 )
82 {
83 // Make sure that the mpa_mul function does not allocate anything
84 // from the POOL by eliminating the reason for doing it.
85 BN_VAR(tempResult, LARGEST_NUMBER_BITS * 2);
86 if(result != multiplicand && result != multiplier)
87 tempResult = result;
88 mpa_mul((mpanum)tempResult, (const mpanum)multiplicand,
89 (const mpanum)multiplier,
90 NULL);
91 BnCopy(result, tempResult);
92 return TRUE;
93 }
94
95 //*** BnDiv()
96 // This function divides two BIGNUM values. The function always returns TRUE.
97 LIB_EXPORT BOOL
BnDiv(bigNum quotient,bigNum remainder,bigConst dividend,bigConst divisor)98 BnDiv(
99 bigNum quotient,
100 bigNum remainder,
101 bigConst dividend,
102 bigConst divisor
103 )
104 {
105 MPA_ENTER(10, LARGEST_NUMBER_BITS);
106 pAssert(!BnEqualZero(divisor));
107 if(BnGetSize(dividend) < BnGetSize(divisor))
108 {
109 if(quotient)
110 BnSetWord(quotient, 0);
111 if(remainder)
112 BnCopy(remainder, dividend);
113 }
114 else
115 {
116 pAssert((quotient == NULL)
117 || (quotient->allocated >=
118 (unsigned)(dividend->size - divisor->size)));
119 pAssert((remainder == NULL)
120 || (remainder->allocated >= divisor->size));
121 mpa_div((mpanum)quotient, (mpanum)remainder,
122 (const mpanum)dividend, (const mpanum)divisor, POOL);
123 }
124 MPA_LEAVE();
125 return TRUE;
126 }
127
128 #ifdef TPM_ALG_RSA
129 //*** BnGcd()
130 // Get the greatest common divisor of two numbers
131 LIB_EXPORT BOOL
BnGcd(bigNum gcd,bigConst number1,bigConst number2)132 BnGcd(
133 bigNum gcd, // OUT: the common divisor
134 bigConst number1, // IN:
135 bigConst number2 // IN:
136 )
137 {
138 MPA_ENTER(20, LARGEST_NUMBER_BITS);
139 //
140 mpa_gcd((mpanum)gcd, (mpanum)number1, (mpanum)number2, POOL);
141 MPA_LEAVE();
142 return TRUE;
143 }
144
145 //***BnModExp()
146 // Do modular exponentiation using BIGNUM values. The conversion from a bignum_t
147 // to a BIGNUM is trivial as they are based on the same structure
148 LIB_EXPORT BOOL
BnModExp(bigNum result,bigConst number,bigConst exponent,bigConst modulus)149 BnModExp(
150 bigNum result, // OUT: the result
151 bigConst number, // IN: number to exponentiate
152 bigConst exponent, // IN:
153 bigConst modulus // IN:
154 )
155 {
156 MPA_ENTER(20, LARGEST_NUMBER_BITS);
157 BN_VAR(bnR, MAX_RSA_KEY_BITS);
158 BN_VAR(bnR2, MAX_RSA_KEY_BITS);
159 mpa_word_t n_inv;
160 mpa_word_t ffmCtx[mpa_fmm_context_size_in_U32(MAX_RSA_KEY_BITS)];
161 //
162 mpa_init_static_fmm_context((mpa_fmm_context_base *)ffmCtx,
163 BYTES_TO_CRYPT_WORDS(sizeof(ffmCtx)));
164 // Generate modular form
165 if(mpa_compute_fmm_context((const mpanum)modulus, (mpanum)bnR,
166 (mpanum)bnR2, &n_inv, POOL) != 0)
167 FAIL(FATAL_ERROR_INTERNAL);
168 // Do exponentiation
169 mpa_exp_mod((mpanum)result, (const mpanum)number, (const mpanum)exponent,
170 (const mpanum)modulus, (const mpanum)bnR, (const mpanum)bnR2,
171 n_inv, POOL);
172 MPA_LEAVE();
173 return TRUE;
174 }
175
176 //*** BnModInverse()
177 // Modular multiplicative inverse
178 LIB_EXPORT BOOL
BnModInverse(bigNum result,bigConst number,bigConst modulus)179 BnModInverse(
180 bigNum result,
181 bigConst number,
182 bigConst modulus
183 )
184 {
185 BOOL retVal;
186 MPA_ENTER(10, LARGEST_NUMBER_BITS);
187 retVal = (mpa_inv_mod((mpanum)result, (const mpanum)number,
188 (const mpanum)modulus, POOL) == 0);
189 MPA_LEAVE();
190 return retVal;
191 }
192 #endif // TPM_ALG_RSA
193
194 #ifdef TPM_ALG_ECC
195
196
197 //*** BnEccModMult()
198 // This function does a point multiply of the form R = [d]S
199 // return type: BOOL
200 // FALSE failure in operation; treat as result being point at infinity
201 LIB_EXPORT BOOL
BnEccModMult(bigPoint R,pointConst S,bigConst d,bigCurve E)202 BnEccModMult(
203 bigPoint R, // OUT: computed point
204 pointConst S, // IN: point to multiply by 'd'
205 bigConst d, // IN: scalar for [d]S
206 bigCurve E
207 )
208 {
209 MPA_ENTER(30, MAX_ECC_KEY_BITS * 2);
210 // The point multiply in LTC seems to need a large reciprocal for
211 // intermediate results
212 POINT_VAR(result, MAX_ECC_KEY_BITS * 4);
213 BOOL OK;
214 //
215 (POOL); // Avoid compiler warning
216 if(S == NULL)
217 S = CurveGetG(AccessCurveData(E));
218 OK = (ltc_ecc_mulmod((mpanum)d, (ecc_point *)S,
219 (ecc_point *)result, (void *)CurveGetPrime(E), 1)
220 == CRYPT_OK);
221 OK = OK && !BnEqualZero(result->z);
222 if(OK)
223 BnPointCopy(R, result);
224
225 MPA_LEAVE();
226 return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
227 }
228
229 //*** BnEccModMult2()
230 // This function does a point multiply of the form R = [d]S + [u]Q
231 // return type: BOOL
232 // FALSE failure in operation; treat as result being point at infinity
233 LIB_EXPORT BOOL
BnEccModMult2(bigPoint R,pointConst S,bigConst d,pointConst Q,bigConst u,bigCurve E)234 BnEccModMult2(
235 bigPoint R, // OUT: computed point
236 pointConst S, // IN: first point (optional)
237 bigConst d, // IN: scalar for [d]S or [d]G
238 pointConst Q, // IN: second point
239 bigConst u, // IN: second scalar
240 bigCurve E // IN: curve
241 )
242 {
243 MPA_ENTER(80, MAX_ECC_KEY_BITS);
244 BOOL OK;
245 // The point multiply in LTC seems to need a large reciprocal for
246 // intermediate results
247 POINT_VAR(result, MAX_ECC_KEY_BITS * 4);
248 //
249 (POOL); // Avoid compiler warning
250 if(S == NULL)
251 S = CurveGetG(AccessCurveData(E));
252
253 OK = (ltc_ecc_mul2add((ecc_point *)S, (mpanum)d, (ecc_point *)Q, (mpanum)u,
254 (ecc_point *)result, (mpanum)CurveGetPrime(E))
255 == CRYPT_OK);
256 OK = OK && !BnEqualZero(result->z);
257
258 if(OK)
259 BnPointCopy(R, result);
260
261 MPA_LEAVE();
262 return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT;
263 }
264
265 //*** BnEccAdd()
266 // This function does addition of two points. Since this is not implemented
267 // in LibTomCrypt() will try to trick it by doing multiply with scalar of 1.
268 // I have no idea if this will work and it's not needed unless MQV or the SM2
269 // variant is enabled.
270 // return type: BOOL
271 // FALSE failure in operation; treat as result being point at infinity
272 LIB_EXPORT BOOL
BnEccAdd(bigPoint R,pointConst S,pointConst Q,bigCurve E)273 BnEccAdd(
274 bigPoint R, // OUT: computed point
275 pointConst S, // IN: point to multiply by 'd'
276 pointConst Q, // IN: second point
277 bigCurve E // IN: curve
278 )
279 {
280 BN_WORD_INITIALIZED(one, 1);
281 return BnEccModMult2(R, S, one, Q, one, E);
282 }
283
284 #endif // TPM_ALG_ECC
285
286 #endif // MATH_LIB_LTC
287