Coverage Report

Created: 2025-07-23 07:04

/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