/src/libtpms/src/tpm2/crypto/openssl/BnToOsslMath.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* */ |
7 | | /* Licenses and Notices */ |
8 | | /* */ |
9 | | /* 1. Copyright Licenses: */ |
10 | | /* */ |
11 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
12 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
13 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
14 | | /* derivative works, distribute, display and perform the Source Code and */ |
15 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
16 | | /* */ |
17 | | /* - The TCG grants to the user of the other parts of the specification */ |
18 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
19 | | /* display, and perform the specification solely for the purpose of */ |
20 | | /* developing products based on such documents. */ |
21 | | /* */ |
22 | | /* 2. Source Code Distribution Conditions: */ |
23 | | /* */ |
24 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
25 | | /* this list of conditions and the following disclaimers. */ |
26 | | /* */ |
27 | | /* - Redistributions in binary form must reproduce the above copyright */ |
28 | | /* licenses, this list of conditions and the following disclaimers in the */ |
29 | | /* documentation and/or other materials provided with the distribution. */ |
30 | | /* */ |
31 | | /* 3. Disclaimers: */ |
32 | | /* */ |
33 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
34 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
35 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
36 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
37 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
38 | | /* information on specification licensing rights available through TCG */ |
39 | | /* membership agreements. */ |
40 | | /* */ |
41 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
42 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
43 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
44 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
45 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
46 | | /* */ |
47 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
48 | | /* liability, including liability for infringement of any proprietary */ |
49 | | /* rights, relating to use of information in this specification and to the */ |
50 | | /* implementation of this specification, and TCG disclaims all liability for */ |
51 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
52 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
53 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
54 | | /* arising in any way out of use or reliance upon this specification or any */ |
55 | | /* information herein. */ |
56 | | /* */ |
57 | | /* (c) Copyright IBM Corp. and others, 2023 */ |
58 | | /* */ |
59 | | /********************************************************************************/ |
60 | | |
61 | | //** Introduction |
62 | | // The functions in this file provide the low-level interface between the TPM code |
63 | | // and the big number and elliptic curve math routines in OpenSSL. |
64 | | // |
65 | | // Most math on big numbers require a context. The context contains the memory in |
66 | | // which OpenSSL creates and manages the big number values. When a OpenSSL math |
67 | | // function will be called that modifies a BIGNUM value, that value must be created in |
68 | | // an OpenSSL context. The first line of code in such a function must be: |
69 | | // OSSL_ENTER(); and the last operation before returning must be OSSL_LEAVE(). |
70 | | // OpenSSL variables can then be created with BnNewVariable(). Constant values to be |
71 | | // used by OpenSSL are created from the bigNum values passed to the functions in this |
72 | | // file. Space for the BIGNUM control block is allocated in the stack of the |
73 | | // function and then it is initialized by calling BigInitialized(). That function |
74 | | // sets up the values in the BIGNUM structure and sets the data pointer to point to |
75 | | // the data in the bignum_t. This is only used when the value is known to be a |
76 | | // constant in the called function. |
77 | | // |
78 | | // Because the allocations of constants is on the local stack and the |
79 | | // OSSL_ENTER()/OSSL_LEAVE() pair flushes everything created in OpenSSL memory, there |
80 | | // should be no chance of a memory leak. |
81 | | |
82 | | //** Includes and Defines |
83 | | //#include "Tpm.h" |
84 | | #include "BnOssl.h" |
85 | | |
86 | | #ifdef MATH_LIB_OSSL |
87 | | # include "BnToOsslMath_fp.h" |
88 | | |
89 | | //** Functions |
90 | | |
91 | | //*** OsslToTpmBn() |
92 | | // This function converts an OpenSSL BIGNUM to a TPM bigNum. In this implementation |
93 | | // it is assumed that OpenSSL uses a different control structure but the same data |
94 | | // layout -- an array of native-endian words in little-endian order. |
95 | | // Return Type: BOOL |
96 | | // TRUE(1) success |
97 | | // FALSE(0) failure because value will not fit or OpenSSL variable doesn't |
98 | | // exist |
99 | | BOOL OsslToTpmBn(bigNum bn, const BIGNUM* osslBn) // libtpms: added 'const' |
100 | 3.55M | { |
101 | 3.55M | GOTO_ERROR_UNLESS(osslBn != NULL); |
102 | | // If the bn is NULL, it means that an output value pointer was NULL meaning that |
103 | | // the results is simply to be discarded. |
104 | 3.55M | unsigned char buffer[LARGEST_NUMBER + 1]; // libtpms added |
105 | 3.55M | int buffer_len; // libtpms added |
106 | | |
107 | 3.55M | if(bn != NULL) |
108 | 1.81M | { |
109 | 1.81M | #if 1 // libtpms: added begin |
110 | 1.81M | int num_bytes; |
111 | | |
112 | 1.81M | num_bytes = BN_num_bytes(osslBn); |
113 | 1.81M | GOTO_ERROR_UNLESS(num_bytes >= 0 && sizeof(buffer) >= (size_t)num_bytes); |
114 | 1.81M | buffer_len = BN_bn2bin(osslBn, buffer); /* ossl to bin */ |
115 | 1.81M | BnFromBytes(bn, buffer, buffer_len); /* bin to TPM */ |
116 | | #else // libtpms: added end |
117 | | int i; |
118 | | // |
119 | | GOTO_ERROR_UNLESS((unsigned)osslBn->top <= BnGetAllocated(bn)); |
120 | | for(i = 0; i < osslBn->top; i++) |
121 | | bn->d[i] = osslBn->d[i]; |
122 | | BnSetTop(bn, osslBn->top); |
123 | | #endif // libtpms: added |
124 | 1.81M | } |
125 | 3.55M | return TRUE; |
126 | 0 | Error: |
127 | 0 | return FALSE; |
128 | 3.55M | } |
129 | | |
130 | | //*** BigInitialized() |
131 | | // This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for |
132 | | // values that are passed to OpenSLL when they are not declared as const in the |
133 | | // function prototype. Instead, use BnNewVariable(). |
134 | | BIGNUM* BigInitialized(BIGNUM* toInit, bigConst initializer) |
135 | 3.70M | { |
136 | 3.70M | #if 1 // libtpms: added begin |
137 | 3.70M | BIGNUM *_toInit; |
138 | 3.70M | unsigned char buffer[LARGEST_NUMBER + 1]; |
139 | 3.70M | NUMBYTES buffer_len = (NUMBYTES )sizeof(buffer); |
140 | 3.70M | #endif // libtpms: added end |
141 | | |
142 | 3.70M | if(initializer == NULL) |
143 | 3.70M | FAIL(FATAL_ERROR_PARAMETER); |
144 | 3.70M | if(toInit == NULL || initializer == NULL) |
145 | 0 | return NULL; |
146 | 3.70M | #if 1 // libtpms: added begin |
147 | 3.70M | BnToBytes(initializer, buffer, &buffer_len); /* TPM to bin */ |
148 | 3.70M | _toInit = BN_bin2bn(buffer, buffer_len, NULL); /* bin to ossl */ |
149 | 3.70M | BN_set_flags(_toInit, BN_FLG_CONSTTIME); |
150 | 3.70M | BN_copy(toInit, _toInit); |
151 | 3.70M | BN_clear_free(_toInit); |
152 | | #else // libtpms: added end |
153 | | toInit->d = (BN_ULONG*)&initializer->d[0]; |
154 | | toInit->dmax = (int)initializer->allocated; |
155 | | toInit->top = (int)initializer->size; |
156 | | toInit->neg = 0; |
157 | | toInit->flags = 0; |
158 | | #endif // libtpms: added |
159 | 3.70M | return toInit; |
160 | 3.70M | } |
161 | | |
162 | | # ifndef OSSL_DEBUG |
163 | | # define BIGNUM_PRINT(label, bn, eol) |
164 | | # define DEBUG_PRINT(x) |
165 | | # else |
166 | | # define DEBUG_PRINT(x) printf("%s", x) |
167 | | # define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol)) |
168 | | |
169 | | //*** BIGNUM_print() |
170 | | static void BIGNUM_print(const char* label, const BIGNUM* a, BOOL eol) |
171 | | { |
172 | | BN_ULONG* d; |
173 | | int i; |
174 | | int notZero = FALSE; |
175 | | |
176 | | if(label != NULL) |
177 | | printf("%s", label); |
178 | | if(a == NULL) |
179 | | { |
180 | | printf("NULL"); |
181 | | goto done; |
182 | | } |
183 | | if(a->neg) |
184 | | printf("-"); |
185 | | for(i = a->top, d = &a->d[i - 1]; i > 0; i--) |
186 | | { |
187 | | int j; |
188 | | BN_ULONG l = *d--; |
189 | | for(j = BN_BITS2 - 8; j >= 0; j -= 8) |
190 | | { |
191 | | BYTE b = (BYTE)((l >> j) & 0xFF); |
192 | | notZero = notZero || (b != 0); |
193 | | if(notZero) |
194 | | printf("%02x", b); |
195 | | } |
196 | | if(!notZero) |
197 | | printf("0"); |
198 | | } |
199 | | done: |
200 | | if(eol) |
201 | | printf("\n"); |
202 | | return; |
203 | | } |
204 | | # endif |
205 | | |
206 | | //*** BnNewVariable() |
207 | | // This function allocates a new variable in the provided context. If the context |
208 | | // does not exist or the allocation fails, it is a catastrophic failure. |
209 | | static BIGNUM* BnNewVariable(BN_CTX* CTX) |
210 | 3.59M | { |
211 | 3.59M | BIGNUM* new; |
212 | | // |
213 | | // This check is intended to protect against calling this function without |
214 | | // having initialized the CTX. |
215 | 3.59M | if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL)) |
216 | 3.59M | FAIL(FATAL_ERROR_ALLOCATION); |
217 | 3.59M | return new; |
218 | 3.59M | } |
219 | | |
220 | | # if LIBRARY_COMPATIBILITY_CHECK |
221 | | |
222 | | //*** MathLibraryCompatibilityCheck() |
223 | | BOOL BnMathLibraryCompatibilityCheck(void) |
224 | 7.24k | { |
225 | 7.24k | OSSL_ENTER(); |
226 | 7.24k | BIGNUM* osslTemp = BnNewVariable(CTX); |
227 | | #if 0 // libtpms: added |
228 | | crypt_uword_t i; |
229 | | #endif // libtpms: added |
230 | 7.24k | BYTE test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, |
231 | 7.24k | 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, |
232 | 7.24k | 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; |
233 | 7.24k | BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value |
234 | | // |
235 | | // Convert the test data to a bigNum |
236 | 7.24k | BnFromBytes(tpmTemp, test, sizeof(test)); |
237 | | // Convert the test data to an OpenSSL BIGNUM |
238 | 7.24k | BN_bin2bn(test, sizeof(test), osslTemp); |
239 | | // Make sure the values are consistent |
240 | | #if 0 // libtpms: added |
241 | | GOTO_ERROR_UNLESS(osslTemp->top == (int)tpmTemp->size); |
242 | | for(i = 0; i < tpmTemp->size; i++) |
243 | | GOTO_ERROR_UNLESS(osslTemp->d[i] == tpmTemp->d[i]); |
244 | | #endif // libtpms: added |
245 | 7.24k | OSSL_LEAVE(); |
246 | 7.24k | return 1; |
247 | | #if 0 // libtpms: added |
248 | | Error: |
249 | | return 0; |
250 | | #endif // libtpms: added |
251 | 7.24k | } |
252 | | # endif |
253 | | |
254 | | //*** BnModMult() |
255 | | // This function does a modular multiply. It first does a multiply and then a divide |
256 | | // and returns the remainder of the divide. |
257 | | // Return Type: BOOL |
258 | | // TRUE(1) success |
259 | | // FALSE(0) failure in operation |
260 | | LIB_EXPORT BOOL BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus) |
261 | 33.2k | { |
262 | 33.2k | OSSL_ENTER(); |
263 | 33.2k | BOOL OK = TRUE; |
264 | 33.2k | BIGNUM* bnResult = BN_NEW(); |
265 | 33.2k | BIGNUM* bnTemp = BN_NEW(); |
266 | 33.2k | BIG_INITIALIZED(bnOp1, op1); |
267 | 33.2k | BIG_INITIALIZED(bnOp2, op2); |
268 | 33.2k | BIG_INITIALIZED(bnMod, modulus); |
269 | | // |
270 | 33.2k | GOTO_ERROR_UNLESS(BN_mul(bnTemp, bnOp1, bnOp2, CTX)); |
271 | 33.2k | GOTO_ERROR_UNLESS(BN_div(NULL, bnResult, bnTemp, bnMod, CTX)); |
272 | 33.2k | GOTO_ERROR_UNLESS(OsslToTpmBn(result, bnResult)); |
273 | 33.2k | goto Exit; |
274 | 33.2k | Error: |
275 | 0 | OK = FALSE; |
276 | 33.2k | Exit: |
277 | 33.2k | BN_clear_free(bnMod); // libtpms added |
278 | 33.2k | BN_clear_free(bnOp2); // libtpms added |
279 | 33.2k | BN_clear_free(bnOp1); // libtpms added |
280 | 33.2k | OSSL_LEAVE(); |
281 | 33.2k | return OK; |
282 | 0 | } |
283 | | |
284 | | //*** BnMult() |
285 | | // Multiplies two numbers |
286 | | // Return Type: BOOL |
287 | | // TRUE(1) success |
288 | | // FALSE(0) failure in operation |
289 | | LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier) |
290 | 2.36k | { |
291 | 2.36k | OSSL_ENTER(); |
292 | 2.36k | BIGNUM* bnTemp = BN_NEW(); |
293 | 2.36k | BOOL OK = TRUE; |
294 | 2.36k | BIG_INITIALIZED(bnA, multiplicand); |
295 | 2.36k | BIG_INITIALIZED(bnB, multiplier); |
296 | | // |
297 | 2.36k | GOTO_ERROR_UNLESS(BN_mul(bnTemp, bnA, bnB, CTX)); |
298 | 2.36k | GOTO_ERROR_UNLESS(OsslToTpmBn(result, bnTemp)); |
299 | 2.36k | goto Exit; |
300 | 2.36k | Error: |
301 | 0 | OK = FALSE; |
302 | 2.36k | Exit: |
303 | 2.36k | BN_clear_free(bnB); // libtpms added |
304 | 2.36k | BN_clear_free(bnA); // libtpms added |
305 | 2.36k | OSSL_LEAVE(); |
306 | 2.36k | return OK; |
307 | 0 | } |
308 | | |
309 | | //*** BnDiv() |
310 | | // This function divides two bigNum values. The function returns FALSE if |
311 | | // there is an error in the operation. |
312 | | // Return Type: BOOL |
313 | | // TRUE(1) success |
314 | | // FALSE(0) failure in operation |
315 | | LIB_EXPORT BOOL BnDiv( |
316 | | bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor) |
317 | 1.74M | { |
318 | 1.74M | OSSL_ENTER(); |
319 | 1.74M | BIGNUM* bnQ = BN_NEW(); |
320 | 1.74M | BIGNUM* bnR = BN_NEW(); |
321 | 1.74M | BOOL OK = TRUE; |
322 | 1.74M | BIG_INITIALIZED(bnDend, dividend); |
323 | 1.74M | BIG_INITIALIZED(bnSor, divisor); |
324 | | // |
325 | 1.74M | if(BnEqualZero(divisor)) |
326 | 1.74M | FAIL(FATAL_ERROR_DIVIDE_ZERO); |
327 | 1.74M | GOTO_ERROR_UNLESS(BN_div(bnQ, bnR, bnDend, bnSor, CTX)); |
328 | 1.74M | GOTO_ERROR_UNLESS(OsslToTpmBn(quotient, bnQ)); |
329 | 1.74M | GOTO_ERROR_UNLESS(OsslToTpmBn(remainder, bnR)); |
330 | 1.74M | DEBUG_PRINT("In BnDiv:\n"); |
331 | 1.74M | BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE); |
332 | 1.74M | BIGNUM_PRINT(" bnDivisor: ", bnSor, TRUE); |
333 | 1.74M | BIGNUM_PRINT(" bnQuotient: ", bnQ, TRUE); |
334 | 1.74M | BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE); |
335 | 1.74M | goto Exit; |
336 | 0 | Error: |
337 | 0 | OK = FALSE; |
338 | 1.74M | Exit: |
339 | 1.74M | BN_clear_free(bnSor); // libtpms added |
340 | 1.74M | BN_clear_free(bnDend); // libtpms added |
341 | 1.74M | OSSL_LEAVE(); |
342 | 1.74M | return OK; |
343 | 0 | } |
344 | | |
345 | | # if ALG_RSA |
346 | | # if !RSA_KEY_SIEVE // libtpms added |
347 | | //*** BnGcd() |
348 | | // Get the greatest common divisor of two numbers |
349 | | // Return Type: BOOL |
350 | | // TRUE(1) success |
351 | | // FALSE(0) failure in operation |
352 | | LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor |
353 | | bigConst number1, // IN: |
354 | | bigConst number2 // IN: |
355 | | ) |
356 | | { |
357 | | OSSL_ENTER(); |
358 | | BIGNUM* bnGcd = BN_NEW(); |
359 | | BOOL OK = TRUE; |
360 | | BIG_INITIALIZED(bn1, number1); |
361 | | BIG_INITIALIZED(bn2, number2); |
362 | | // |
363 | | BN_set_flags(bn1, BN_FLG_CONSTTIME); // number1 is secret prime number |
364 | | GOTO_ERROR_UNLESS(BN_gcd(bnGcd, bn1, bn2, CTX)); |
365 | | GOTO_ERROR_UNLESS(OsslToTpmBn(gcd, bnGcd)); |
366 | | goto Exit; |
367 | | Error: |
368 | | OK = FALSE; |
369 | | Exit: |
370 | | BN_clear_free(bn2); // libtpms added |
371 | | BN_clear_free(bn1); // libtpms added |
372 | | OSSL_LEAVE(); |
373 | | return OK; |
374 | | } |
375 | | # endif // libtpms added |
376 | | |
377 | | //***BnModExp() |
378 | | // Do modular exponentiation using bigNum values. The conversion from a bignum_t to |
379 | | // a bigNum is trivial as they are based on the same structure |
380 | | // Return Type: BOOL |
381 | | // TRUE(1) success |
382 | | // FALSE(0) failure in operation |
383 | | LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result |
384 | | bigConst number, // IN: number to exponentiate |
385 | | bigConst exponent, // IN: |
386 | | bigConst modulus // IN: |
387 | | ) |
388 | 34.1k | { |
389 | 34.1k | OSSL_ENTER(); |
390 | 34.1k | BIGNUM* bnResult = BN_NEW(); |
391 | 34.1k | BOOL OK = TRUE; |
392 | 34.1k | BIG_INITIALIZED(bnN, number); |
393 | 34.1k | BIG_INITIALIZED(bnE, exponent); |
394 | 34.1k | BIG_INITIALIZED(bnM, modulus); |
395 | | // |
396 | 34.1k | BN_set_flags(bnE, BN_FLG_CONSTTIME); // exponent may be private |
397 | 34.1k | GOTO_ERROR_UNLESS(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX)); |
398 | 34.1k | GOTO_ERROR_UNLESS(OsslToTpmBn(result, bnResult)); |
399 | 34.1k | goto Exit; |
400 | 34.1k | Error: |
401 | 0 | OK = FALSE; |
402 | 34.1k | Exit: |
403 | 34.1k | BN_clear_free(bnM); // libtpms added |
404 | 34.1k | BN_clear_free(bnE); // libtpms added |
405 | 34.1k | BN_clear_free(bnN); // libtpms added |
406 | 34.1k | OSSL_LEAVE(); |
407 | 34.1k | return OK; |
408 | 0 | } |
409 | | # endif // ALG_RSA |
410 | | |
411 | | //*** BnModInverse() |
412 | | // Modular multiplicative inverse |
413 | | // Return Type: BOOL |
414 | | // TRUE(1) success |
415 | | // FALSE(0) failure in operation |
416 | | LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus) |
417 | 1.33k | { |
418 | 1.33k | OSSL_ENTER(); |
419 | 1.33k | BIGNUM* bnResult = BN_NEW(); |
420 | 1.33k | BOOL OK = TRUE; |
421 | 1.33k | BIG_INITIALIZED(bnN, number); |
422 | 1.33k | BIG_INITIALIZED(bnM, modulus); |
423 | | // |
424 | 1.33k | BN_set_flags(bnN, BN_FLG_CONSTTIME); // number may be private |
425 | 1.33k | GOTO_ERROR_UNLESS(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL); |
426 | 1.33k | GOTO_ERROR_UNLESS(OsslToTpmBn(result, bnResult)); |
427 | 1.33k | goto Exit; |
428 | 1.33k | Error: |
429 | 2 | OK = FALSE; |
430 | 1.33k | Exit: |
431 | 1.33k | BN_clear_free(bnM); // libtpms added |
432 | 1.33k | BN_clear_free(bnN); // libtpms added |
433 | 1.33k | OSSL_LEAVE(); |
434 | 1.33k | return OK; |
435 | 2 | } |
436 | | |
437 | | # if ALG_ECC |
438 | | |
439 | | //*** PointFromOssl() |
440 | | // Function to copy the point result from an OSSL function to a bigNum |
441 | | // Return Type: BOOL |
442 | | // TRUE(1) success |
443 | | // FALSE(0) failure in operation |
444 | | static BOOL PointFromOssl(bigPoint pOut, // OUT: resulting point |
445 | | EC_POINT* pIn, // IN: the point to return |
446 | | const bigCurveData* E // IN: the curve |
447 | | ) |
448 | 400 | { |
449 | 400 | BIGNUM* x = NULL; |
450 | 400 | BIGNUM* y = NULL; |
451 | 400 | BOOL OK; |
452 | 400 | BN_CTX_start(E->CTX); |
453 | | // |
454 | 400 | x = BN_CTX_get(E->CTX); |
455 | 400 | y = BN_CTX_get(E->CTX); |
456 | | |
457 | 400 | if(y == NULL) |
458 | 400 | FAIL(FATAL_ERROR_ALLOCATION); |
459 | | // If this returns false, then the point is at infinity |
460 | 400 | OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX); |
461 | 400 | if(OK) |
462 | 400 | { |
463 | 400 | OsslToTpmBn(pOut->x, x); |
464 | 400 | OsslToTpmBn(pOut->y, y); |
465 | 400 | BnSetWord(pOut->z, 1); |
466 | 400 | } |
467 | 0 | else |
468 | 0 | BnSetWord(pOut->z, 0); |
469 | 400 | BN_CTX_end(E->CTX); |
470 | 400 | return OK; |
471 | 400 | } |
472 | | |
473 | | //*** EcPointInitialized() |
474 | | // Allocate and initialize a point. |
475 | | LIB_EXPORT EC_POINT* EcPointInitialized(pointConst initializer, const bigCurveData* E) // libtpms: exported function |
476 | 714 | { |
477 | 714 | EC_POINT* P = NULL; |
478 | | |
479 | 714 | if(initializer != NULL) |
480 | 590 | { |
481 | 590 | BIG_INITIALIZED(bnX, initializer->x); |
482 | 590 | BIG_INITIALIZED(bnY, initializer->y); |
483 | 590 | if(E == NULL) |
484 | 590 | FAIL(FATAL_ERROR_ALLOCATION); |
485 | 590 | P = EC_POINT_new(E->G); |
486 | 590 | if(P != NULL && // libtpms added |
487 | 590 | !EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX)) |
488 | 0 | P = NULL; |
489 | 590 | BN_clear_free(bnX); // libtpms added |
490 | 590 | BN_clear_free(bnY); // libtpms added |
491 | 590 | } |
492 | 714 | return P; |
493 | 714 | } |
494 | | |
495 | | //*** BnCurveInitialize() |
496 | | // This function initializes the OpenSSL curve information structure. This |
497 | | // structure points to the TPM-defined values for the curve, to the context for the |
498 | | // number values in the frame, and to the OpenSSL-defined group values. |
499 | | // Return Type: bigCurveData* |
500 | | // NULL the TPM_ECC_CURVE is not valid or there was a problem in |
501 | | // in initializing the curve data |
502 | | // non-NULL points to 'E' |
503 | | LIB_EXPORT bigCurveData* BnCurveInitialize( |
504 | | bigCurveData* E, // IN: curve structure to initialize |
505 | | TPM_ECC_CURVE curveId // IN: curve identifier |
506 | | ) |
507 | 1.66k | { |
508 | 1.66k | const TPMBN_ECC_CURVE_CONSTANTS* C = BnGetCurveData(curveId); |
509 | 1.66k | if(C == NULL) |
510 | 0 | E = NULL; |
511 | 1.66k | if(E != NULL) |
512 | 1.66k | { |
513 | | // This creates the OpenSSL memory context that stays in effect as long as the |
514 | | // curve (E) is defined. |
515 | 1.66k | OSSL_ENTER(); // if the allocation fails, the TPM fails |
516 | 1.66k | EC_POINT* P = NULL; |
517 | 1.66k | BIG_INITIALIZED(bnP, C->prime); |
518 | 1.66k | BIG_INITIALIZED(bnA, C->a); |
519 | 1.66k | BIG_INITIALIZED(bnB, C->b); |
520 | 1.66k | BIG_INITIALIZED(bnX, C->base.x); |
521 | 1.66k | BIG_INITIALIZED(bnY, C->base.y); |
522 | 1.66k | BIG_INITIALIZED(bnN, C->order); |
523 | 1.66k | BIG_INITIALIZED(bnH, C->h); |
524 | | // |
525 | 1.66k | E->C = C; |
526 | 1.66k | E->CTX = CTX; |
527 | | |
528 | | // initialize EC group, associate a generator point and initialize the point |
529 | | // from the parameter data |
530 | | // Create a group structure |
531 | 1.66k | E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX); |
532 | 1.66k | GOTO_ERROR_UNLESS(E->G != NULL); |
533 | | |
534 | | // Allocate a point in the group that will be used in setting the |
535 | | // generator. This is not needed after the generator is set. |
536 | 1.66k | P = EC_POINT_new(E->G); |
537 | 1.66k | GOTO_ERROR_UNLESS(P != NULL); |
538 | | |
539 | | // Need to use this in case Montgomery method is being used |
540 | 1.66k | GOTO_ERROR_UNLESS( |
541 | 1.66k | EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX)); |
542 | | // Now set the generator |
543 | 1.66k | GOTO_ERROR_UNLESS(EC_GROUP_set_generator(E->G, P, bnN, bnH)); |
544 | | |
545 | 1.66k | EC_POINT_free(P); |
546 | 1.66k | goto Exit_free; // libtpms changed |
547 | 0 | Error: |
548 | 0 | EC_POINT_free(P); |
549 | 0 | BnCurveFree(E); |
550 | 0 | E = NULL; |
551 | |
|
552 | 1.66k | Exit_free: // libtpms added begin |
553 | 1.66k | BN_clear_free(bnH); |
554 | 1.66k | BN_clear_free(bnN); |
555 | 1.66k | BN_clear_free(bnY); |
556 | 1.66k | BN_clear_free(bnX); |
557 | 1.66k | BN_clear_free(bnB); |
558 | 1.66k | BN_clear_free(bnA); |
559 | 1.66k | BN_clear_free(bnP); // libtpms added end |
560 | 1.66k | } |
561 | | // Exit: |
562 | 1.66k | return E; |
563 | 1.66k | } |
564 | | |
565 | | //*** BnCurveFree() |
566 | | // This function will free the allocated components of the curve and end the |
567 | | // frame in which the curve data exists |
568 | | LIB_EXPORT void BnCurveFree(bigCurveData* E) |
569 | 1.66k | { |
570 | 1.66k | if(E) |
571 | 1.66k | { |
572 | 1.66k | EC_GROUP_free(E->G); |
573 | 1.66k | OsslContextLeave(E->CTX); |
574 | 1.66k | } |
575 | 1.66k | } |
576 | | |
577 | | //*** BnEccModMult() |
578 | | // This function does a point multiply of the form R = [d]S |
579 | | // Return Type: BOOL |
580 | | // TRUE(1) success |
581 | | // FALSE(0) failure in operation; treat as result being point at infinity |
582 | | LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point |
583 | | pointConst S, // IN: point to multiply by 'd' (optional) |
584 | | bigConst d, // IN: scalar for [d]S |
585 | | const bigCurveData* E) |
586 | 258 | { |
587 | 258 | EC_POINT* pR = EC_POINT_new(E->G); |
588 | 258 | EC_POINT* pS = EcPointInitialized(S, E); |
589 | 258 | BIG_INITIALIZED(bnD, d); |
590 | | |
591 | 258 | if(S == NULL) |
592 | 124 | EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX); |
593 | 134 | else |
594 | 134 | EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX); |
595 | 258 | PointFromOssl(R, pR, E); |
596 | 258 | EC_POINT_clear_free(pR); // libtpms changed |
597 | 258 | EC_POINT_clear_free(pS); // libtpms changed |
598 | 258 | BN_clear_free(bnD); // libtpms added |
599 | 258 | return !BnEqualZero(R->z); |
600 | 258 | } |
601 | | |
602 | | //*** BnEccModMult2() |
603 | | // This function does a point multiply of the form R = [d]G + [u]Q |
604 | | // Return Type: BOOL |
605 | | // TRUE(1) success |
606 | | // FALSE(0) failure in operation; treat as result being point at infinity |
607 | | LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point |
608 | | pointConst S, // IN: optional point |
609 | | bigConst d, // IN: scalar for [d]S or [d]G |
610 | | pointConst Q, // IN: second point |
611 | | bigConst u, // IN: second scalar |
612 | | const bigCurveData* E // IN: curve |
613 | | ) |
614 | 142 | { |
615 | 142 | EC_POINT* pR = EC_POINT_new(E->G); |
616 | 142 | EC_POINT* pS = EcPointInitialized(S, E); |
617 | 142 | BIG_INITIALIZED(bnD, d); |
618 | 142 | EC_POINT* pQ = EcPointInitialized(Q, E); |
619 | 142 | BIG_INITIALIZED(bnU, u); |
620 | | |
621 | 142 | if(S == NULL || S == (pointConst) & (AccessCurveConstants(E)->base)) |
622 | 142 | EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX); |
623 | 0 | else |
624 | 0 | { |
625 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x4010000fL) |
626 | | EC_POINT *pR1 = EC_POINT_new(E->G); |
627 | | EC_POINT *pR2 = EC_POINT_new(E->G); |
628 | | int OK; |
629 | | |
630 | | pAssert(pR1 && pR2); |
631 | | OK = EC_POINT_mul(E->G, pR1, NULL, pS, bnD, E->CTX); |
632 | | OK &= EC_POINT_mul(E->G, pR2, NULL, pQ, bnU, E->CTX); |
633 | | OK &= EC_POINT_add(E->G, pR, pR1, pR2, E->CTX); |
634 | | pAssert(OK); |
635 | | |
636 | | EC_POINT_clear_free(pR1); |
637 | | EC_POINT_clear_free(pR2); |
638 | | #else |
639 | 0 | const EC_POINT* points[2]; |
640 | 0 | const BIGNUM* scalars[2]; |
641 | 0 | points[0] = pS; |
642 | 0 | points[1] = pQ; |
643 | 0 | scalars[0] = bnD; |
644 | 0 | scalars[1] = bnU; |
645 | 0 | EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX); |
646 | 0 | #endif |
647 | 0 | } |
648 | 142 | PointFromOssl(R, pR, E); |
649 | 142 | EC_POINT_clear_free(pR); // libtpms changed |
650 | 142 | EC_POINT_clear_free(pS); // libtpms changed |
651 | 142 | EC_POINT_clear_free(pQ); // libtpms changed |
652 | 142 | BN_clear_free(bnD); // libtpms added |
653 | 142 | BN_clear_free(bnU); // libtpms added |
654 | | |
655 | 142 | return !BnEqualZero(R->z); |
656 | 142 | } |
657 | | |
658 | | //** BnEccAdd() |
659 | | // This function does addition of two points. |
660 | | // Return Type: BOOL |
661 | | // TRUE(1) success |
662 | | // FALSE(0) failure in operation; treat as result being point at infinity |
663 | | LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point |
664 | | pointConst S, // IN: first point to add |
665 | | pointConst Q, // IN: second point |
666 | | const bigCurveData* E // IN: curve |
667 | | ) |
668 | 0 | { |
669 | 0 | EC_POINT* pR = EC_POINT_new(E->G); |
670 | 0 | EC_POINT* pS = EcPointInitialized(S, E); |
671 | 0 | EC_POINT* pQ = EcPointInitialized(Q, E); |
672 | | // |
673 | 0 | EC_POINT_add(E->G, pR, pS, pQ, E->CTX); |
674 | |
|
675 | 0 | PointFromOssl(R, pR, E); |
676 | 0 | EC_POINT_clear_free(pR); // libtpms changed |
677 | 0 | EC_POINT_clear_free(pS); // libtpms changed |
678 | 0 | EC_POINT_clear_free(pQ); // libtpms changed |
679 | 0 | return !BnEqualZero(R->z); |
680 | 0 | } |
681 | | |
682 | | # endif // ALG_ECC |
683 | | |
684 | | #endif // MATHLIB OSSL |