1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 4: Supporting Routines 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include <string.h> 9 10 #include "OsslCryptoEngine.h" 11 12 #ifdef TPM_ALG_ECC 13 #include "CpriDataEcc.h" 14 #include "CpriDataEcc.c" 15 // 16 // 17 // Functions 18 // 19 // _cpri__EccStartup() 20 // 21 // This function is called at TPM Startup to initialize the crypto units. 22 // In this implementation, no initialization is performed at startup but a future version may initialize the self- 23 // test functions here. 24 // 25 LIB_EXPORT BOOL 26 _cpri__EccStartup( 27 void 28 ) 29 { 30 return TRUE; 31 } 32 // 33 // 34 // _cpri__GetCurveIdByIndex() 35 // 36 // This function returns the number of the i-th implemented curve. The normal use would be to call this 37 // function with i starting at 0. When the i is greater than or equal to the number of implemented curves, 38 // TPM_ECC_NONE is returned. 39 // 40 LIB_EXPORT TPM_ECC_CURVE 41 _cpri__GetCurveIdByIndex( 42 UINT16 i 43 ) 44 { 45 if(i >= ECC_CURVE_COUNT) 46 return TPM_ECC_NONE; 47 return eccCurves[i].curveId; 48 } 49 LIB_EXPORT UINT32 50 _cpri__EccGetCurveCount( 51 void 52 ) 53 { 54 return ECC_CURVE_COUNT; 55 } 56 // 57 // 58 // _cpri__EccGetParametersByCurveId() 59 // 60 // This function returns a pointer to the curve data that is associated with the indicated curveId. If there is no 61 // curve with the indicated ID, the function returns NULL. 62 // 63 // 64 // 65 // 66 // Return Value Meaning 67 // 68 // NULL curve with the indicated TPM_ECC_CURVE value is not 69 // implemented 70 // non-NULL pointer to the curve data 71 // 72 LIB_EXPORT const ECC_CURVE * 73 _cpri__EccGetParametersByCurveId( 74 TPM_ECC_CURVE curveId // IN: the curveID 75 ) 76 { 77 int i; 78 for(i = 0; i < ECC_CURVE_COUNT; i++) 79 { 80 if(eccCurves[i].curveId == curveId) 81 return &eccCurves[i]; 82 } 83 FAIL(FATAL_ERROR_INTERNAL); 84 85 return NULL; // Never reached. 86 } 87 static const ECC_CURVE_DATA * 88 GetCurveData( 89 TPM_ECC_CURVE curveId // IN: the curveID 90 ) 91 { 92 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); 93 return curve->curveData; 94 } 95 // 96 // 97 // Point2B() 98 // 99 // This function makes a TPMS_ECC_POINT from a BIGNUM EC_POINT. 100 // 101 static BOOL 102 Point2B( 103 EC_GROUP *group, // IN: group for the point 104 TPMS_ECC_POINT *p, // OUT: receives the converted point 105 EC_POINT *ecP, // IN: the point to convert 106 INT16 size, // IN: size of the coordinates 107 BN_CTX *context // IN: working context 108 ) 109 { 110 BIGNUM *bnX; 111 BIGNUM *bnY; 112 BN_CTX_start(context); 113 bnX = BN_CTX_get(context); 114 bnY = BN_CTX_get(context); 115 if( bnY == NULL 116 // Get the coordinate values 117 || EC_POINT_get_affine_coordinates_GFp(group, ecP, bnX, bnY, context) != 1 118 // Convert x 119 || (!BnTo2B(&p->x.b, bnX, size)) 120 // Convert y 121 || (!BnTo2B(&p->y.b, bnY, size)) 122 ) 123 FAIL(FATAL_ERROR_INTERNAL); 124 BN_CTX_end(context); 125 return TRUE; 126 } 127 // 128 // 129 // EccCurveInit() 130 // 131 // This function initializes the OpenSSL() group definition structure 132 // This function is only used within this file. 133 // It is a fatal error if groupContext is not provided. 134 // 135 // Return Value Meaning 136 // 137 // NULL the TPM_ECC_CURVE is not valid 138 // non-NULL points to a structure in groupContext static EC_GROUP * 139 // 140 static EC_GROUP * 141 EccCurveInit( 142 TPM_ECC_CURVE curveId, // IN: the ID of the curve 143 BN_CTX *groupContext // IN: the context in which the group is to be 144 // created 145 ) 146 { 147 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 148 EC_GROUP *group = NULL; 149 EC_POINT *P = NULL; 150 BN_CTX *context; 151 BIGNUM *bnP; 152 BIGNUM *bnA; 153 BIGNUM *bnB; 154 BIGNUM *bnX; 155 BIGNUM *bnY; 156 BIGNUM *bnN; 157 BIGNUM *bnH; 158 int ok = FALSE; 159 // Context must be provided and curve selector must be valid 160 pAssert(groupContext != NULL && curveData != NULL); 161 context = BN_CTX_new(); 162 if(context == NULL) 163 FAIL(FATAL_ERROR_ALLOCATION); 164 BN_CTX_start(context); 165 bnP = BN_CTX_get(context); 166 bnA = BN_CTX_get(context); 167 bnB = BN_CTX_get(context); 168 bnX = BN_CTX_get(context); 169 bnY = BN_CTX_get(context); 170 bnN = BN_CTX_get(context); 171 bnH = BN_CTX_get(context); 172 if (bnH == NULL) 173 goto Cleanup; 174 // Convert the number formats 175 BnFrom2B(bnP, curveData->p); 176 BnFrom2B(bnA, curveData->a); 177 BnFrom2B(bnB, curveData->b); 178 BnFrom2B(bnX, curveData->x); 179 BnFrom2B(bnY, curveData->y); 180 BnFrom2B(bnN, curveData->n); 181 BnFrom2B(bnH, curveData->h); 182 // initialize EC group, associate a generator point and initialize the point 183 // from the parameter data 184 ok = ( (group = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, groupContext)) != NULL 185 && (P = EC_POINT_new(group)) != NULL 186 && EC_POINT_set_affine_coordinates_GFp(group, P, bnX, bnY, groupContext) 187 && EC_GROUP_set_generator(group, P, bnN, bnH) 188 ); 189 Cleanup: 190 if (!ok && group != NULL) 191 { 192 EC_GROUP_free(group); 193 group = NULL; 194 } 195 if(P != NULL) 196 EC_POINT_free(P); 197 BN_CTX_end(context); 198 BN_CTX_free(context); 199 return group; 200 } 201 // 202 // 203 // PointFrom2B() 204 // 205 // This function sets the coordinates of an existing BN Point from a TPMS_ECC_POINT. 206 // 207 static EC_POINT * 208 PointFrom2B( 209 EC_GROUP *group, // IN: the group for the point 210 EC_POINT *ecP, // IN: an existing BN point in the group 211 TPMS_ECC_POINT *p, // IN: the 2B coordinates of the point 212 BN_CTX *context // IN: the BIGNUM context 213 ) 214 { 215 BIGNUM *bnX; 216 BIGNUM *bnY; 217 // If the point is not allocated then just return a NULL 218 if(ecP == NULL) 219 return NULL; 220 BN_CTX_start(context); 221 bnX = BN_CTX_get(context); 222 bnY = BN_CTX_get(context); 223 if( // Set the coordinates of the point 224 bnY == NULL 225 || BN_bin2bn(p->x.t.buffer, p->x.t.size, bnX) == NULL 226 || BN_bin2bn(p->y.t.buffer, p->y.t.size, bnY) == NULL 227 || !EC_POINT_set_affine_coordinates_GFp(group, ecP, bnX, bnY, context) 228 ) 229 FAIL(FATAL_ERROR_INTERNAL); 230 BN_CTX_end(context); 231 return ecP; 232 } 233 // 234 // 235 // EccInitPoint2B() 236 // 237 // This function allocates a point in the provided group and initializes it with the values in a 238 // TPMS_ECC_POINT. 239 // 240 static EC_POINT * 241 EccInitPoint2B( 242 EC_GROUP *group, // IN: group for the point 243 TPMS_ECC_POINT *p, // IN: the coordinates for the point 244 BN_CTX *context // IN: the BIGNUM context 245 ) 246 { 247 EC_POINT *ecP; 248 BN_CTX_start(context); 249 ecP = EC_POINT_new(group); 250 if(PointFrom2B(group, ecP, p, context) == NULL) 251 FAIL(FATAL_ERROR_INTERNAL); 252 BN_CTX_end(context); 253 return ecP; 254 } 255 // 256 // 257 // PointMul() 258 // 259 // This function does a point multiply and checks for the result being the point at infinity. Q = ([A]G + [B]P) 260 // 261 // Return Value Meaning 262 // 263 // CRYPT_NO_RESULT point is at infinity 264 // CRYPT_SUCCESS point not at infinity 265 // 266 static CRYPT_RESULT 267 PointMul( 268 EC_GROUP *group, // IN: group curve 269 EC_POINT *ecpQ, // OUT: result 270 BIGNUM *bnA, // IN: scalar for [A]G 271 EC_POINT *ecpP, // IN: point for [B]P 272 BIGNUM *bnB, // IN: scalar for [B]P 273 BN_CTX *context // IN: working context 274 ) 275 { 276 if(EC_POINT_mul(group, ecpQ, bnA, ecpP, bnB, context) != 1) 277 FAIL(FATAL_ERROR_INTERNAL); 278 if(EC_POINT_is_at_infinity(group, ecpQ)) 279 return CRYPT_NO_RESULT; 280 return CRYPT_SUCCESS; 281 } 282 // 283 // 284 // GetRandomPrivate() 285 // 286 // This function gets a random value (d) to use as a private ECC key and then qualifies the key so that it is 287 // between 0 < d < n. 288 // It is a fatal error if dOut or pIn is not provided or if the size of pIn is larger than MAX_ECC_KEY_BYTES 289 // (the largest buffer size of a TPM2B_ECC_PARAMETER) 290 // 291 static void 292 GetRandomPrivate( 293 TPM2B_ECC_PARAMETER *dOut, // OUT: the qualified random value 294 const TPM2B *pIn // IN: the maximum value for the key 295 ) 296 { 297 int i; 298 BYTE *pb; 299 pAssert(pIn != NULL && dOut != NULL && pIn->size <= MAX_ECC_KEY_BYTES); 300 // Set the size of the output 301 dOut->t.size = pIn->size; 302 // Get some random bits 303 while(TRUE) 304 { 305 _cpri__GenerateRandom(dOut->t.size, dOut->t.buffer); 306 // See if the d < n 307 if(memcmp(dOut->t.buffer, pIn->buffer, pIn->size) < 0) 308 { 309 // dOut < n so make sure that 0 < dOut 310 for(pb = dOut->t.buffer, i = dOut->t.size; i > 0; i--) 311 { 312 if(*pb++ != 0) 313 return; 314 } 315 } 316 } 317 } 318 // 319 // 320 // _cpri__EccPointMultiply 321 // 322 // This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are points on 323 // the specified curve and G is the default generator of the curve. 324 // The xOut and yOut parameters are optional and may be set to NULL if not used. 325 // It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be provided. If dIn and 326 // QIn are specified but uIn is not provided, then R = [dIn]QIn. 327 // If the multiply produces the point at infinity, the CRYPT_NO_RESULT is returned. 328 // The sizes of xOut and yOut' will be set to be the size of the degree of the curve 329 // It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is unspecified. 330 // 331 // 332 // 333 // 334 // Return Value Meaning 335 // 336 // CRYPT_SUCCESS point multiplication succeeded 337 // CRYPT_POINT the point Qin is not on the curve 338 // CRYPT_NO_RESULT the product point is at infinity 339 // 340 LIB_EXPORT CRYPT_RESULT 341 _cpri__EccPointMultiply( 342 TPMS_ECC_POINT *Rout, // OUT: the product point R 343 TPM_ECC_CURVE curveId, // IN: the curve to use 344 TPM2B_ECC_PARAMETER *dIn, // IN: value to multiply against the 345 // curve generator 346 TPMS_ECC_POINT *Qin, // IN: point Q 347 TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier 348 // of Q 349 ) 350 { 351 BN_CTX *context; 352 BIGNUM *bnD; 353 BIGNUM *bnU; 354 EC_GROUP *group; 355 EC_POINT *R = NULL; 356 EC_POINT *Q = NULL; 357 CRYPT_RESULT retVal = CRYPT_SUCCESS; 358 // Validate that the required parameters are provided. 359 pAssert((dIn != NULL || uIn != NULL) && (Qin != NULL || dIn != NULL)); 360 // If a point is provided for the multiply, make sure that it is on the curve 361 if(Qin != NULL && !_cpri__EccIsPointOnCurve(curveId, Qin)) 362 return CRYPT_POINT; 363 context = BN_CTX_new(); 364 if(context == NULL) 365 FAIL(FATAL_ERROR_ALLOCATION); 366 BN_CTX_start(context); 367 bnU = BN_CTX_get(context); 368 bnD = BN_CTX_get(context); 369 group = EccCurveInit(curveId, context); 370 // There should be no path for getting a bad curve ID into this function. 371 pAssert(group != NULL); 372 // check allocations should have worked and allocate R 373 if( bnD == NULL 374 || (R = EC_POINT_new(group)) == NULL) 375 FAIL(FATAL_ERROR_ALLOCATION); 376 // If Qin is present, create the point 377 if(Qin != NULL) 378 { 379 // Assume the size variables do not overflow. This should not happen in 380 // the contexts in which this function will be called. 381 assert2Bsize(Qin->x.t); 382 assert2Bsize(Qin->x.t); 383 Q = EccInitPoint2B(group, Qin, context); 384 } 385 if(dIn != NULL) 386 { 387 // Assume the size variables do not overflow, which should not happen in 388 // the contexts that this function will be called. 389 assert2Bsize(dIn->t); 390 BnFrom2B(bnD, &dIn->b); 391 } 392 else 393 bnD = NULL; 394 // If uIn is specified, initialize its BIGNUM 395 if(uIn != NULL) 396 { 397 // Assume the size variables do not overflow, which should not happen in 398 // the contexts that this function will be called. 399 assert2Bsize(uIn->t); 400 BnFrom2B(bnU, &uIn->b); 401 } 402 // If uIn is not specified but Q is, then we are going to 403 // do R = [d]Q 404 else if(Qin != NULL) 405 { 406 bnU = bnD; 407 bnD = NULL; 408 } 409 // If neither Q nor u is specified, then null this pointer 410 else 411 bnU = NULL; 412 // Use the generator of the curve 413 if((retVal = PointMul(group, R, bnD, Q, bnU, context)) == CRYPT_SUCCESS) 414 Point2B(group, Rout, R, (INT16) ((EC_GROUP_get_degree(group)+7)/8), context); 415 if (Q) 416 EC_POINT_free(Q); 417 if(R) 418 EC_POINT_free(R); 419 if(group) 420 EC_GROUP_free(group); 421 BN_CTX_end(context); 422 BN_CTX_free(context); 423 return retVal; 424 } 425 // 426 // 427 // ClearPoint2B() 428 // 429 // Initialize the size values of a point 430 // 431 static void 432 ClearPoint2B( 433 TPMS_ECC_POINT *p // IN: the point 434 ) 435 { 436 if(p != NULL) { 437 p->x.t.size = 0; 438 p->y.t.size = 0; 439 } 440 } 441 #if defined TPM_ALG_ECDAA || defined TPM_ALG_SM2 //% 442 // 443 // 444 // _cpri__EccCommitCompute() 445 // 446 // This function performs the point multiply operations required by TPM2_Commit(). 447 // If B or M is provided, they must be on the curve defined by curveId. This routine does not check that they 448 // are on the curve and results are unpredictable if they are not. 449 // 450 // 451 // 452 // It is a fatal error if r or d is NULL. If B is not NULL, then it is a fatal error if K and L are both NULL. If M is 453 // not NULL, then it is a fatal error if E is NULL. 454 // 455 // Return Value Meaning 456 // 457 // CRYPT_SUCCESS computations completed normally 458 // CRYPT_NO_RESULT if K, L or E was computed to be the point at infinity 459 // CRYPT_CANCEL a cancel indication was asserted during this function 460 // 461 LIB_EXPORT CRYPT_RESULT 462 _cpri__EccCommitCompute( 463 TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q 464 TPMS_ECC_POINT *L, // OUT: [r]B 465 TPMS_ECC_POINT *E, // OUT: [r]M 466 TPM_ECC_CURVE curveId, // IN: the curve for the computations 467 TPMS_ECC_POINT *M, // IN: M (optional) 468 TPMS_ECC_POINT *B, // IN: B (optional) 469 TPM2B_ECC_PARAMETER *d, // IN: d (required) 470 TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) 471 ) 472 { 473 BN_CTX *context; 474 BIGNUM *bnY, *bnR, *bnD; 475 EC_GROUP *group; 476 EC_POINT *pK = NULL, *pL = NULL, *pE = NULL, *pM = NULL, *pB = NULL; 477 UINT16 keySizeInBytes; 478 CRYPT_RESULT retVal = CRYPT_SUCCESS; 479 // Validate that the required parameters are provided. 480 // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do 481 // E := [r]Q if both M and B are NULL. 482 483 pAssert((r && (K || !B) && (L || !B)) || (E || (!M && B))); 484 context = BN_CTX_new(); 485 if(context == NULL) 486 FAIL(FATAL_ERROR_ALLOCATION); 487 BN_CTX_start(context); 488 bnR = BN_CTX_get(context); 489 bnD = BN_CTX_get(context); 490 bnY = BN_CTX_get(context); 491 if(bnY == NULL) 492 FAIL(FATAL_ERROR_ALLOCATION); 493 // Initialize the output points in case they are not computed 494 ClearPoint2B(K); 495 ClearPoint2B(L); 496 ClearPoint2B(E); 497 if((group = EccCurveInit(curveId, context)) == NULL) 498 { 499 retVal = CRYPT_PARAMETER; 500 goto Cleanup2; 501 } 502 keySizeInBytes = (UINT16) ((EC_GROUP_get_degree(group)+7)/8); 503 // Sizes of the r and d parameters may not be zero 504 pAssert(((int) r->t.size > 0) && ((int) d->t.size > 0)); 505 // Convert scalars to BIGNUM 506 BnFrom2B(bnR, &r->b); 507 BnFrom2B(bnD, &d->b); 508 // If B is provided, compute K=[d]B and L=[r]B 509 if(B != NULL) 510 { 511 // Allocate the points to receive the value 512 if( (pK = EC_POINT_new(group)) == NULL 513 || (pL = EC_POINT_new(group)) == NULL) 514 FAIL(FATAL_ERROR_ALLOCATION); 515 // need to compute K = [d]B 516 // Allocate and initialize BIGNUM version of B 517 pB = EccInitPoint2B(group, B, context); 518 // do the math for K = [d]B 519 if((retVal = PointMul(group, pK, NULL, pB, bnD, context)) != CRYPT_SUCCESS) 520 goto Cleanup; 521 // Convert BN K to TPM2B K 522 Point2B(group, K, pK, (INT16)keySizeInBytes, context); 523 // compute L= [r]B after checking for cancel 524 if(_plat__IsCanceled()) 525 { 526 retVal = CRYPT_CANCEL; 527 goto Cleanup; 528 } 529 // compute L = [r]B 530 if((retVal = PointMul(group, pL, NULL, pB, bnR, context)) != CRYPT_SUCCESS) 531 goto Cleanup; 532 // Convert BN L to TPM2B L 533 Point2B(group, L, pL, (INT16)keySizeInBytes, context); 534 } 535 if(M != NULL || B == NULL) 536 { 537 // if this is the third point multiply, check for cancel first 538 if(B != NULL && _plat__IsCanceled()) 539 { 540 retVal = CRYPT_CANCEL; 541 goto Cleanup; 542 } 543 // Allocate E 544 if((pE = EC_POINT_new(group)) == NULL) 545 FAIL(FATAL_ERROR_ALLOCATION); 546 // Create BIGNUM version of M unless M is NULL 547 if(M != NULL) 548 { 549 // M provided so initialize a BIGNUM M and compute E = [r]M 550 pM = EccInitPoint2B(group, M, context); 551 retVal = PointMul(group, pE, NULL, pM, bnR, context); 552 } 553 else 554 // compute E = [r]G (this is only done if M and B are both NULL 555 retVal = PointMul(group, pE, bnR, NULL, NULL, context); 556 if(retVal == CRYPT_SUCCESS) 557 // Convert E to 2B format 558 Point2B(group, E, pE, (INT16)keySizeInBytes, context); 559 } 560 Cleanup: 561 EC_GROUP_free(group); 562 if(pK != NULL) EC_POINT_free(pK); 563 if(pL != NULL) EC_POINT_free(pL); 564 if(pE != NULL) EC_POINT_free(pE); 565 if(pM != NULL) EC_POINT_free(pM); 566 if(pB != NULL) EC_POINT_free(pB); 567 Cleanup2: 568 BN_CTX_end(context); 569 BN_CTX_free(context); 570 return retVal; 571 } 572 #endif //% 573 // 574 // 575 // _cpri__EccIsPointOnCurve() 576 // 577 // This function is used to test if a point is on a defined curve. It does this by checking that y^2 mod p = x^3 578 // + a*x + b mod p 579 // It is a fatal error if Q is not specified (is NULL). 580 // 581 // Return Value Meaning 582 // 583 // TRUE point is on curve 584 // FALSE point is not on curve or curve is not supported 585 // 586 LIB_EXPORT BOOL 587 _cpri__EccIsPointOnCurve( 588 TPM_ECC_CURVE curveId, // IN: the curve selector 589 TPMS_ECC_POINT *Q // IN: the point. 590 ) 591 { 592 BN_CTX *context; 593 BIGNUM *bnX; 594 BIGNUM *bnY; 595 BIGNUM *bnA; 596 BIGNUM *bnB; 597 BIGNUM *bnP; 598 BIGNUM *bn3; 599 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 600 BOOL retVal; 601 pAssert(Q != NULL && curveData != NULL); 602 if((context = BN_CTX_new()) == NULL) 603 FAIL(FATAL_ERROR_ALLOCATION); 604 BN_CTX_start(context); 605 bnX = BN_CTX_get(context); 606 bnY = BN_CTX_get(context); 607 bnA = BN_CTX_get(context); 608 bnB = BN_CTX_get(context); 609 bn3 = BN_CTX_get(context); 610 bnP = BN_CTX_get(context); 611 if(bnP == NULL) 612 FAIL(FATAL_ERROR_ALLOCATION); 613 // Convert values 614 if ( !BN_bin2bn(Q->x.t.buffer, Q->x.t.size, bnX) 615 || !BN_bin2bn(Q->y.t.buffer, Q->y.t.size, bnY) 616 || !BN_bin2bn(curveData->p->buffer, curveData->p->size, bnP) 617 || !BN_bin2bn(curveData->a->buffer, curveData->a->size, bnA) 618 || !BN_set_word(bn3, 3) 619 || !BN_bin2bn(curveData->b->buffer, curveData->b->size, bnB) 620 ) 621 FAIL(FATAL_ERROR_INTERNAL); 622 // The following sequence is probably not optimal but it seems to be correct. 623 // compute x^3 + a*x + b mod p 624 // first, compute a*x mod p 625 if( !BN_mod_mul(bnA, bnA, bnX, bnP, context) 626 // 627 // next, compute a*x + b mod p 628 || !BN_mod_add(bnA, bnA, bnB, bnP, context) 629 // next, compute X^3 mod p 630 || !BN_mod_exp(bnX, bnX, bn3, bnP, context) 631 // finally, compute x^3 + a*x + b mod p 632 || !BN_mod_add(bnX, bnX, bnA, bnP, context) 633 // then compute y^2 634 || !BN_mod_mul(bnY, bnY, bnY, bnP, context) 635 ) 636 FAIL(FATAL_ERROR_INTERNAL); 637 retVal = BN_cmp(bnX, bnY) == 0; 638 BN_CTX_end(context); 639 BN_CTX_free(context); 640 return retVal; 641 } 642 // 643 // 644 // _cpri__GenerateKeyEcc() 645 // 646 // This function generates an ECC key pair based on the input parameters. This routine uses KDFa() to 647 // produce candidate numbers. The method is according to FIPS 186-3, section B.4.1 "GKey() Pair 648 // Generation Using Extra Random Bits." According to the method in FIPS 186-3, the resulting private value 649 // d should be 1 <= d < n where n is the order of the base point. In this implementation, the range of the 650 // private value is further restricted to be 2^(nLen/2) <= d < n where nLen is the order of n. 651 // 652 // EXAMPLE: If the curve is NIST-P256, then nLen is 256 bits and d will need to be between 2^128 <= d < n 653 // 654 // It is a fatal error if Qout, dOut, or seed is not provided (is NULL). 655 // 656 // Return Value Meaning 657 // 658 // CRYPT_PARAMETER the hash algorithm is not supported 659 // 660 LIB_EXPORT CRYPT_RESULT 661 _cpri__GenerateKeyEcc( 662 TPMS_ECC_POINT *Qout, // OUT: the public point 663 TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar 664 TPM_ECC_CURVE curveId, // IN: the curve identifier 665 TPM_ALG_ID hashAlg, // IN: hash algorithm to use in the key 666 // generation process 667 TPM2B *seed, // IN: the seed to use 668 const char *label, // IN: A label for the generation 669 // process. 670 TPM2B *extra, // IN: Party 1 data for the KDF 671 UINT32 *counter // IN/OUT: Counter value to allow KDF 672 // iteration to be propagated across 673 // multiple functions 674 ) 675 { 676 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 677 INT16 keySizeInBytes; 678 UINT32 count = 0; 679 CRYPT_RESULT retVal; 680 UINT16 hLen = _cpri__GetDigestSize(hashAlg); 681 BIGNUM *bnNm1; // Order of the curve minus one 682 BIGNUM *bnD; // the private scalar 683 BN_CTX *context; // the context for the BIGNUM values 684 BYTE withExtra[MAX_ECC_KEY_BYTES + 8]; // trial key with 685 //extra bits 686 TPM2B_4_BYTE_VALUE marshaledCounter = {.t = {4}}; 687 UINT32 totalBits; 688 // Validate parameters (these are fatal) 689 pAssert( seed != NULL && dOut != NULL && Qout != NULL && curveData != NULL); 690 // Non-fatal parameter checks. 691 if(hLen <= 0) 692 return CRYPT_PARAMETER; 693 // allocate the local BN values 694 context = BN_CTX_new(); 695 if(context == NULL) 696 FAIL(FATAL_ERROR_ALLOCATION); 697 BN_CTX_start(context); 698 bnNm1 = BN_CTX_get(context); 699 bnD = BN_CTX_get(context); 700 // The size of the input scalars is limited by the size of the size of a 701 // TPM2B_ECC_PARAMETER. Make sure that it is not irrational. 702 pAssert((int) curveData->n->size <= MAX_ECC_KEY_BYTES); 703 if( bnD == NULL 704 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnNm1) == NULL 705 || (keySizeInBytes = (INT16) BN_num_bytes(bnNm1)) > MAX_ECC_KEY_BYTES) 706 FAIL(FATAL_ERROR_INTERNAL); 707 // get the total number of bits 708 totalBits = BN_num_bits(bnNm1) + 64; 709 // Reduce bnNm1 from 'n' to 'n' - 1 710 BN_sub_word(bnNm1, 1); 711 // Initialize the count value 712 if(counter != NULL) 713 count = *counter; 714 if(count == 0) 715 count = 1; 716 // Start search for key (should be quick) 717 for(; count != 0; count++) 718 { 719 UINT32_TO_BYTE_ARRAY(count, marshaledCounter.t.buffer); 720 _cpri__KDFa(hashAlg, seed, label, extra, &marshaledCounter.b, 721 totalBits, withExtra, NULL, FALSE); 722 // Convert the result and modular reduce 723 // Assume the size variables do not overflow, which should not happen in 724 // the contexts that this function will be called. 725 pAssert(keySizeInBytes <= MAX_ECC_KEY_BYTES); 726 if ( BN_bin2bn(withExtra, keySizeInBytes+8, bnD) == NULL 727 || BN_mod(bnD, bnD, bnNm1, context) != 1) 728 FAIL(FATAL_ERROR_INTERNAL); 729 // Add one to get 0 < d < n 730 BN_add_word(bnD, 1); 731 if(BnTo2B(&dOut->b, bnD, keySizeInBytes) != 1) 732 FAIL(FATAL_ERROR_INTERNAL); 733 // Do the point multiply to create the public portion of the key. If 734 // the multiply generates the point at infinity (unlikely), do another 735 // iteration. 736 if( (retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL)) 737 != CRYPT_NO_RESULT) 738 break; 739 } 740 if(count == 0) // if counter wrapped, then the TPM should go into failure mode 741 FAIL(FATAL_ERROR_INTERNAL); 742 // Free up allocated BN values 743 BN_CTX_end(context); 744 BN_CTX_free(context); 745 if(counter != NULL) 746 *counter = count; 747 return retVal; 748 } 749 // 750 // 751 // _cpri__GetEphemeralEcc() 752 // 753 // This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the 754 // key will be discarded 755 // 756 LIB_EXPORT CRYPT_RESULT 757 _cpri__GetEphemeralEcc( 758 TPMS_ECC_POINT *Qout, // OUT: the public point 759 TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar 760 TPM_ECC_CURVE curveId // IN: the curve for the key 761 ) 762 { 763 CRYPT_RESULT retVal; 764 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 765 pAssert(curveData != NULL); 766 // Keep getting random values until one is found that doesn't create a point 767 // at infinity. This will never, ever, ever, ever, ever, happen but if it does 768 // we have to get a next random value. 769 while(TRUE) 770 { 771 GetRandomPrivate(dOut, curveData->p); 772 // _cpri__EccPointMultiply does not return CRYPT_ECC_POINT if no point is 773 // provided. CRYPT_PARAMTER should not be returned because the curve ID 774 // has to be supported. Thus the only possible error is CRYPT_NO_RESULT. 775 retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL); 776 if(retVal != CRYPT_NO_RESULT) 777 return retVal; // Will return CRYPT_SUCCESS 778 } 779 } 780 #ifdef TPM_ALG_ECDSA //% 781 // 782 // 783 // SignEcdsa() 784 // 785 // This function implements the ECDSA signing algorithm. The method is described in the comments below. 786 // It is a fatal error if rOut, sOut, dIn, or digest are not provided. 787 // 788 LIB_EXPORT CRYPT_RESULT 789 SignEcdsa( 790 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature 791 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature 792 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 793 // process 794 TPM2B_ECC_PARAMETER *dIn, // IN: the private key 795 TPM2B *digest // IN: the value to sign 796 ) 797 { 798 BIGNUM *bnK; 799 BIGNUM *bnIk; 800 BIGNUM *bnN; 801 BIGNUM *bnR; 802 // 803 BIGNUM *bnD; 804 BIGNUM *bnZ; 805 TPM2B_ECC_PARAMETER k; 806 TPMS_ECC_POINT R; 807 BN_CTX *context; 808 CRYPT_RESULT retVal = CRYPT_SUCCESS; 809 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 810 pAssert(rOut != NULL && sOut != NULL && dIn != NULL && digest != NULL); 811 context = BN_CTX_new(); 812 if(context == NULL) 813 FAIL(FATAL_ERROR_ALLOCATION); 814 BN_CTX_start(context); 815 bnN = BN_CTX_get(context); 816 bnZ = BN_CTX_get(context); 817 bnR = BN_CTX_get(context); 818 bnD = BN_CTX_get(context); 819 bnIk = BN_CTX_get(context); 820 bnK = BN_CTX_get(context); 821 // Assume the size variables do not overflow, which should not happen in 822 // the contexts that this function will be called. 823 pAssert(curveData->n->size <= MAX_ECC_PARAMETER_BYTES); 824 if( bnK == NULL 825 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) 826 FAIL(FATAL_ERROR_INTERNAL); 827 // The algorithm as described in "Suite B Implementer's Guide to FIPS 186-3(ECDSA)" 828 // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a per-message 829 // secret number and its inverse modulo n. Since n is prime, the 830 // output will be invalid only if there is a failure in the RBG. 831 // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar 832 // multiplication (see [Routines]), where G is the base point included in 833 // the set of domain parameters. 834 // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1. 835 // 4. Use the selected hash function to compute H = Hash(M). 836 // 5. Convert the bit string H to an integer e as described in Appendix B.2. 837 // 6. Compute s = (k^-1 * (e + d * r)) mod n. If s = 0, return to Step 1.2. 838 // 7. Return (r, s). 839 // Generate a random value k in the range 1 <= k < n 840 // Want a K value that is the same size as the curve order 841 k.t.size = curveData->n->size; 842 while(TRUE) // This implements the loop at step 6. If s is zero, start over. 843 { 844 while(TRUE) 845 { 846 // Step 1 and 2 -- generate an ephemeral key and the modular inverse 847 // of the private key. 848 while(TRUE) 849 { 850 GetRandomPrivate(&k, curveData->n); 851 // Do the point multiply to generate a point and check to see if 852 // the point it at infinity 853 if( _cpri__EccPointMultiply(&R, curveId, &k, NULL, NULL) 854 != CRYPT_NO_RESULT) 855 break; // can only be CRYPT_SUCCESS 856 } 857 // x coordinate is mod p. Make it mod n 858 // Assume the size variables do not overflow, which should not happen 859 // in the contexts that this function will be called. 860 assert2Bsize(R.x.t); 861 BN_bin2bn(R.x.t.buffer, R.x.t.size, bnR); 862 BN_mod(bnR, bnR, bnN, context); 863 // Make sure that it is not zero; 864 if(BN_is_zero(bnR)) 865 continue; 866 // Make sure that a modular inverse exists 867 // Assume the size variables do not overflow, which should not happen 868 // in the contexts that this function will be called. 869 assert2Bsize(k.t); 870 BN_bin2bn(k.t.buffer, k.t.size, bnK); 871 if( BN_mod_inverse(bnIk, bnK, bnN, context) != NULL) 872 break; 873 } 874 // Set z = leftmost bits of the digest 875 // NOTE: This is implemented such that the key size needs to be 876 // an even number of bytes in length. 877 if(digest->size > curveData->n->size) 878 { 879 // Assume the size variables do not overflow, which should not happen 880 // in the contexts that this function will be called. 881 pAssert(curveData->n->size <= MAX_ECC_KEY_BYTES); 882 // digest is larger than n so truncate 883 BN_bin2bn(digest->buffer, curveData->n->size, bnZ); 884 } 885 else 886 { 887 // Assume the size variables do not overflow, which should not happen 888 // in the contexts that this function will be called. 889 pAssert(digest->size <= MAX_DIGEST_SIZE); 890 // digest is same or smaller than n so use it all 891 BN_bin2bn(digest->buffer, digest->size, bnZ); 892 } 893 // Assume the size variables do not overflow, which should not happen in 894 // the contexts that this function will be called. 895 assert2Bsize(dIn->t); 896 if( bnZ == NULL 897 // need the private scalar of the signing key 898 || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL) 899 FAIL(FATAL_ERROR_INTERNAL); 900 // NOTE: When the result of an operation is going to be reduced mod x 901 // any modular multiplication is done so that the intermediate values 902 // don't get too large. 903 // 904 // now have inverse of K (bnIk), z (bnZ), r (bnR), d (bnD) and n (bnN) 905 // Compute s = k^-1 (z + r*d)(mod n) 906 // first do d = r*d mod n 907 if( !BN_mod_mul(bnD, bnR, bnD, bnN, context) 908 // d = z + r * d 909 || !BN_add(bnD, bnZ, bnD) 910 // d = k^(-1)(z + r * d)(mod n) 911 || !BN_mod_mul(bnD, bnIk, bnD, bnN, context) 912 // convert to TPM2B format 913 || !BnTo2B(&sOut->b, bnD, curveData->n->size) 914 // and write the modular reduced version of r 915 // NOTE: this was deferred to reduce the number of 916 // error checks. 917 || !BnTo2B(&rOut->b, bnR, curveData->n->size)) 918 FAIL(FATAL_ERROR_INTERNAL); 919 if(!BN_is_zero(bnD)) 920 break; // signature not zero so done 921 // if the signature value was zero, start over 922 } 923 // Free up allocated BN values 924 BN_CTX_end(context); 925 BN_CTX_free(context); 926 return retVal; 927 } 928 #endif //% 929 #if defined TPM_ALG_ECDAA || defined TPM_ALG_ECSCHNORR //% 930 // 931 // 932 // EcDaa() 933 // 934 // This function is used to perform a modified Schnorr signature for ECDAA. 935 // This function performs s = k + T * d mod n where 936 // a) 'k is a random, or pseudo-random value used in the commit phase 937 // b) T is the digest to be signed, and 938 // c) d is a private key. 939 // If tIn is NULL then use tOut as T 940 // 941 // Return Value Meaning 942 // 943 // CRYPT_SUCCESS signature created 944 // 945 static CRYPT_RESULT 946 EcDaa( 947 TPM2B_ECC_PARAMETER *tOut, // OUT: T component of the signature 948 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature 949 TPM_ECC_CURVE curveId, // IN: the curve used in signing 950 TPM2B_ECC_PARAMETER *dIn, // IN: the private key 951 TPM2B *tIn, // IN: the value to sign 952 TPM2B_ECC_PARAMETER *kIn // IN: a random value from commit 953 ) 954 { 955 BIGNUM *bnN, *bnK, *bnT, *bnD; 956 BN_CTX *context; 957 const TPM2B *n; 958 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 959 BOOL OK = TRUE; 960 // Parameter checks 961 pAssert( sOut != NULL && dIn != NULL && tOut != NULL 962 && kIn != NULL && curveData != NULL); 963 // this just saves key strokes 964 n = curveData->n; 965 if(tIn != NULL) 966 Copy2B(&tOut->b, tIn); 967 // The size of dIn and kIn input scalars is limited by the size of the size 968 // of a TPM2B_ECC_PARAMETER and tIn can be no larger than a digest. 969 // Make sure they are within range. 970 pAssert( (int) dIn->t.size <= MAX_ECC_KEY_BYTES 971 && (int) kIn->t.size <= MAX_ECC_KEY_BYTES 972 // 973 && (int) tOut->t.size <= MAX_DIGEST_SIZE 974 ); 975 context = BN_CTX_new(); 976 if(context == NULL) 977 FAIL(FATAL_ERROR_ALLOCATION); 978 BN_CTX_start(context); 979 bnN = BN_CTX_get(context); 980 bnK = BN_CTX_get(context); 981 bnT = BN_CTX_get(context); 982 bnD = BN_CTX_get(context); 983 // Check for allocation problems 984 if(bnD == NULL) 985 FAIL(FATAL_ERROR_ALLOCATION); 986 // Convert values 987 if( BN_bin2bn(n->buffer, n->size, bnN) == NULL 988 || BN_bin2bn(kIn->t.buffer, kIn->t.size, bnK) == NULL 989 || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL 990 || BN_bin2bn(tOut->t.buffer, tOut->t.size, bnT) == NULL) 991 FAIL(FATAL_ERROR_INTERNAL); 992 // Compute T = T mod n 993 OK = OK && BN_mod(bnT, bnT, bnN, context); 994 // compute (s = k + T * d mod n) 995 // d = T * d mod n 996 OK = OK && BN_mod_mul(bnD, bnT, bnD, bnN, context) == 1; 997 // d = k + T * d mod n 998 OK = OK && BN_mod_add(bnD, bnK, bnD, bnN, context) == 1; 999 // s = d 1000 OK = OK && BnTo2B(&sOut->b, bnD, n->size); 1001 // r = T 1002 OK = OK && BnTo2B(&tOut->b, bnT, n->size); 1003 if(!OK) 1004 FAIL(FATAL_ERROR_INTERNAL); 1005 // Cleanup 1006 BN_CTX_end(context); 1007 BN_CTX_free(context); 1008 return CRYPT_SUCCESS; 1009 } 1010 #endif //% 1011 #ifdef TPM_ALG_ECSCHNORR //% 1012 // 1013 // 1014 // Mod2B() 1015 // 1016 // Function does modular reduction of TPM2B values. 1017 // 1018 static CRYPT_RESULT 1019 Mod2B( 1020 TPM2B *x, // IN/OUT: value to reduce 1021 const TPM2B *n // IN: mod 1022 ) 1023 { 1024 int compare; 1025 compare = _math__uComp(x->size, x->buffer, n->size, n->buffer); 1026 if(compare < 0) 1027 // if x < n, then mod is x 1028 return CRYPT_SUCCESS; 1029 if(compare == 0) 1030 { 1031 // if x == n then mod is 0 1032 x->size = 0; 1033 x->buffer[0] = 0; 1034 return CRYPT_SUCCESS; 1035 } 1036 return _math__Div(x, n, NULL, x); 1037 } 1038 1039 // 1040 // 1041 // SchnorrEcc() 1042 // 1043 // This function is used to perform a modified Schnorr signature. 1044 // This function will generate a random value k and compute 1045 // a) (xR, yR) = [k]G 1046 // b) r = hash(P || xR)(mod n) 1047 // c) s= k + r * ds 1048 // d) return the tuple T, s 1049 // 1050 // 1051 // 1052 // 1053 // Return Value Meaning 1054 // 1055 // CRYPT_SUCCESS signature created 1056 // CRYPT_SCHEME hashAlg can't produce zero-length digest 1057 // 1058 static CRYPT_RESULT 1059 SchnorrEcc( 1060 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature 1061 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature 1062 TPM_ALG_ID hashAlg, // IN: hash algorithm used 1063 TPM_ECC_CURVE curveId, // IN: the curve used in signing 1064 TPM2B_ECC_PARAMETER *dIn, // IN: the private key 1065 TPM2B *digest, // IN: the digest to sign 1066 TPM2B_ECC_PARAMETER *kIn // IN: for testing 1067 ) 1068 { 1069 TPM2B_ECC_PARAMETER k; 1070 BIGNUM *bnR, *bnN, *bnK, *bnT, *bnD; 1071 BN_CTX *context; 1072 const TPM2B *n; 1073 EC_POINT *pR = NULL; 1074 EC_GROUP *group = NULL; 1075 CPRI_HASH_STATE hashState; 1076 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); 1077 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1078 TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_PARAMETER_BYTES)); 1079 TPM2B_T T2b; 1080 BOOL OK = TRUE; 1081 // Parameter checks 1082 // Must have a place for the 'r' and 's' parts of the signature, a private 1083 // key ('d') 1084 pAssert( rOut != NULL && sOut != NULL && dIn != NULL 1085 && digest != NULL && curveData != NULL); 1086 // to save key strokes 1087 n = curveData->n; 1088 // If the digest does not produce a hash, then null the signature and return 1089 // a failure. 1090 if(digestSize == 0) 1091 { 1092 rOut->t.size = 0; 1093 sOut->t.size = 0; 1094 return CRYPT_SCHEME; 1095 } 1096 // Allocate big number values 1097 context = BN_CTX_new(); 1098 if(context == NULL) 1099 FAIL(FATAL_ERROR_ALLOCATION); 1100 BN_CTX_start(context); 1101 bnR = BN_CTX_get(context); 1102 bnN = BN_CTX_get(context); 1103 bnK = BN_CTX_get(context); 1104 bnT = BN_CTX_get(context); 1105 bnD = BN_CTX_get(context); 1106 if( bnD == NULL 1107 // initialize the group parameters 1108 || (group = EccCurveInit(curveId, context)) == NULL 1109 // allocate a local point 1110 || (pR = EC_POINT_new(group)) == NULL 1111 ) 1112 FAIL(FATAL_ERROR_ALLOCATION); 1113 if(BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) 1114 FAIL(FATAL_ERROR_INTERNAL); 1115 while(OK) 1116 { 1117 // a) set k to a random value such that 1 k n-1 1118 if(kIn != NULL) 1119 { 1120 Copy2B(&k.b, &kIn->b); // copy input k if testing 1121 OK = FALSE; // not OK to loop 1122 } 1123 else 1124 // If get a random value in the correct range 1125 GetRandomPrivate(&k, n); 1126 // Convert 'k' and generate pR = ['k']G 1127 BnFrom2B(bnK, &k.b); 1128 // b) compute E (xE, yE) [k]G 1129 if(PointMul(group, pR, bnK, NULL, NULL, context) == CRYPT_NO_RESULT) 1130 // c) if E is the point at infinity, go to a) 1131 continue; 1132 // d) compute e xE (mod n) 1133 // Get the x coordinate of the point 1134 EC_POINT_get_affine_coordinates_GFp(group, pR, bnR, NULL, context); 1135 // make (mod n) 1136 BN_mod(bnR, bnR, bnN, context); 1137 // e) if e is zero, go to a) 1138 if(BN_is_zero(bnR)) 1139 continue; 1140 // Convert xR to a string (use T as a temp) 1141 BnTo2B(&T2b.b, bnR, (UINT16)(BN_num_bits(bnR)+7)/8); 1142 // f) compute r HschemeHash(P || e) (mod n) 1143 _cpri__StartHash(hashAlg, FALSE, &hashState); 1144 _cpri__UpdateHash(&hashState, digest->size, digest->buffer); 1145 _cpri__UpdateHash(&hashState, T2b.t.size, T2b.t.buffer); 1146 if(_cpri__CompleteHash(&hashState, digestSize, T2b.b.buffer) != digestSize) 1147 FAIL(FATAL_ERROR_INTERNAL); 1148 T2b.t.size = digestSize; 1149 BnFrom2B(bnT, &T2b.b); 1150 BN_div(NULL, bnT, bnT, bnN, context); 1151 BnTo2B(&rOut->b, bnT, (UINT16)BN_num_bytes(bnT)); 1152 // We have a value and we are going to exit the loop successfully 1153 OK = TRUE; 1154 break; 1155 } 1156 // Cleanup 1157 EC_POINT_free(pR); 1158 EC_GROUP_free(group); 1159 BN_CTX_end(context); 1160 BN_CTX_free(context); 1161 // If we have a value, finish the signature 1162 if(OK) 1163 return EcDaa(rOut, sOut, curveId, dIn, NULL, &k); 1164 else 1165 return CRYPT_NO_RESULT; 1166 } 1167 #endif //% 1168 #ifdef TPM_ALG_SM2 //% 1169 #ifdef _SM2_SIGN_DEBUG //% 1170 static int 1171 cmp_bn2hex( 1172 BIGNUM *bn, // IN: big number value 1173 const char *c // IN: character string number 1174 ) 1175 { 1176 int result; 1177 BIGNUM *bnC = BN_new(); 1178 pAssert(bnC != NULL); 1179 BN_hex2bn(&bnC, c); 1180 result = BN_ucmp(bn, bnC); 1181 BN_free(bnC); 1182 return result; 1183 } 1184 static int 1185 cmp_2B2hex( 1186 TPM2B *a, // IN: TPM2B number to compare 1187 const char *c // IN: character string 1188 ) 1189 { 1190 int result; 1191 int sl = strlen(c); 1192 BIGNUM *bnA; 1193 result = (a->size * 2) - sl; 1194 if(result != 0) 1195 return result; 1196 pAssert((bnA = BN_bin2bn(a->buffer, a->size, NULL)) != NULL); 1197 result = cmp_bn2hex(bnA, c); 1198 BN_free(bnA); 1199 return result; 1200 } 1201 static void 1202 cpy_hexTo2B( 1203 TPM2B *b, // OUT: receives value 1204 const char *c // IN: source string 1205 ) 1206 { 1207 BIGNUM *bnB = BN_new(); 1208 pAssert((strlen(c) & 1) == 0); // must have an even number of digits 1209 b->size = strlen(c) / 2; 1210 BN_hex2bn(&bnB, c); 1211 pAssert(bnB != NULL); 1212 BnTo2B(b, bnB, b->size); 1213 BN_free(bnB); 1214 } 1215 #endif //% _SM2_SIGN_DEBUG 1216 // 1217 // 1218 // SignSM2() 1219 // 1220 // This function signs a digest using the method defined in SM2 Part 2. The method in the standard will add 1221 // a header to the message to be signed that is a hash of the values that define the key. This then hashed 1222 // with the message to produce a digest (e) that is signed. This function signs e. 1223 // 1224 // 1225 // 1226 // 1227 // Return Value Meaning 1228 // 1229 // CRYPT_SUCCESS sign worked 1230 // 1231 static CRYPT_RESULT 1232 SignSM2( 1233 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature 1234 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature 1235 TPM_ECC_CURVE curveId, // IN: the curve used in signing 1236 TPM2B_ECC_PARAMETER *dIn, // IN: the private key 1237 TPM2B *digest // IN: the digest to sign 1238 ) 1239 { 1240 BIGNUM *bnR; 1241 BIGNUM *bnS; 1242 BIGNUM *bnN; 1243 BIGNUM *bnK; 1244 BIGNUM *bnX1; 1245 BIGNUM *bnD; 1246 BIGNUM *bnT; // temp 1247 BIGNUM *bnE; 1248 BN_CTX *context; 1249 TPM2B_ECC_PARAMETER k; 1250 TPMS_ECC_POINT p2Br; 1251 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1252 pAssert(curveData != NULL); 1253 context = BN_CTX_new(); 1254 BN_CTX_start(context); 1255 bnK = BN_CTX_get(context); 1256 bnR = BN_CTX_get(context); 1257 bnS = BN_CTX_get(context); 1258 bnX1 = BN_CTX_get(context); 1259 bnN = BN_CTX_get(context); 1260 bnD = BN_CTX_get(context); 1261 bnT = BN_CTX_get(context); 1262 bnE = BN_CTX_get(context); 1263 if(bnE == NULL) 1264 FAIL(FATAL_ERROR_ALLOCATION); 1265 BnFrom2B(bnE, digest); 1266 BnFrom2B(bnN, curveData->n); 1267 BnFrom2B(bnD, &dIn->b); 1268 #ifdef _SM2_SIGN_DEBUG 1269 BN_hex2bn(&bnE, "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76"); 1270 BN_hex2bn(&bnD, "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"); 1271 #endif 1272 // A3: Use random number generator to generate random number 1 <= k <= n-1; 1273 // NOTE: Ax: numbers are from the SM2 standard 1274 k.t.size = curveData->n->size; 1275 loop: 1276 { 1277 // Get a random number 1278 _cpri__GenerateRandom(k.t.size, k.t.buffer); 1279 #ifdef _SM2_SIGN_DEBUG 1280 BN_hex2bn(&bnK, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F"); 1281 BnTo2B(&k.b,bnK, 32); 1282 k.t.size = 32; 1283 #endif 1284 //make sure that the number is 0 < k < n 1285 BnFrom2B(bnK, &k.b); 1286 if( BN_ucmp(bnK, bnN) >= 0 1287 || BN_is_zero(bnK)) 1288 goto loop; 1289 // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according 1290 // to details specified in 4.2.7 in Part 1 of this document, transform the 1291 // data type of x1 into an integer; 1292 if( _cpri__EccPointMultiply(&p2Br, curveId, &k, NULL, NULL) 1293 == CRYPT_NO_RESULT) 1294 goto loop; 1295 BnFrom2B(bnX1, &p2Br.x.b); 1296 // A5: Figure out r = (e + x1) mod n, 1297 if(!BN_mod_add(bnR, bnE, bnX1, bnN, context)) 1298 FAIL(FATAL_ERROR_INTERNAL); 1299 #ifdef _SM2_SIGN_DEBUG 1300 pAssert(cmp_bn2hex(bnR, 1301 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") 1302 == 0); 1303 #endif 1304 // if r=0 or r+k=n, return to A3; 1305 if(!BN_add(bnT, bnK, bnR)) 1306 FAIL(FATAL_ERROR_INTERNAL); 1307 if(BN_is_zero(bnR) || BN_ucmp(bnT, bnN) == 0) 1308 goto loop; 1309 // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, if s=0, return to A3; 1310 // compute t = (1+d)-1 1311 BN_copy(bnT, bnD); 1312 if( !BN_add_word(bnT, 1) 1313 || !BN_mod_inverse(bnT, bnT, bnN, context) // (1 + dA)^-1 mod n 1314 ) 1315 FAIL(FATAL_ERROR_INTERNAL); 1316 #ifdef _SM2_SIGN_DEBUG 1317 pAssert(cmp_bn2hex(bnT, 1318 "79BFCF3052C80DA7B939E0C6914A18CBB2D96D8555256E83122743A7D4F5F956") 1319 == 0); 1320 #endif 1321 // compute s = t * (k - r * dA) mod n 1322 if( !BN_mod_mul(bnS, bnD, bnR, bnN, context) // (r * dA) mod n 1323 || !BN_mod_sub(bnS, bnK, bnS, bnN, context) // (k - (r * dA) mod n 1324 || !BN_mod_mul(bnS, bnT, bnS, bnN, context))// t * (k - (r * dA) mod n 1325 FAIL(FATAL_ERROR_INTERNAL); 1326 #ifdef _SM2_SIGN_DEBUG 1327 pAssert(cmp_bn2hex(bnS, 1328 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") 1329 == 0); 1330 #endif 1331 if(BN_is_zero(bnS)) 1332 goto loop; 1333 } 1334 // A7: According to details specified in 4.2.1 in Part 1 of this document, transform 1335 // the data type of r, s into bit strings, signature of message M is (r, s). 1336 BnTo2B(&rOut->b, bnR, curveData->n->size); 1337 BnTo2B(&sOut->b, bnS, curveData->n->size); 1338 #ifdef _SM2_SIGN_DEBUG 1339 pAssert(cmp_2B2hex(&rOut->b, 1340 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") 1341 == 0); 1342 pAssert(cmp_2B2hex(&sOut->b, 1343 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") 1344 == 0); 1345 #endif 1346 BN_CTX_end(context); 1347 BN_CTX_free(context); 1348 return CRYPT_SUCCESS; 1349 } 1350 #endif //% TPM_ALG_SM2 1351 // 1352 // 1353 // _cpri__SignEcc() 1354 // 1355 // This function is the dispatch function for the various ECC-based signing schemes. 1356 // 1357 // Return Value Meaning 1358 // 1359 // CRYPT_SCHEME scheme is not supported 1360 // 1361 LIB_EXPORT CRYPT_RESULT 1362 _cpri__SignEcc( 1363 TPM2B_ECC_PARAMETER *rOut, // OUT: r component of the signature 1364 TPM2B_ECC_PARAMETER *sOut, // OUT: s component of the signature 1365 TPM_ALG_ID scheme, // IN: the scheme selector 1366 TPM_ALG_ID hashAlg, // IN: the hash algorithm if need 1367 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 1368 // process 1369 TPM2B_ECC_PARAMETER *dIn, // IN: the private key 1370 TPM2B *digest, // IN: the digest to sign 1371 TPM2B_ECC_PARAMETER *kIn // IN: k for input 1372 ) 1373 { 1374 switch (scheme) 1375 { 1376 case TPM_ALG_ECDSA: 1377 // SignEcdsa always works 1378 return SignEcdsa(rOut, sOut, curveId, dIn, digest); 1379 break; 1380 #ifdef TPM_ALG_ECDAA 1381 case TPM_ALG_ECDAA: 1382 if(rOut != NULL) 1383 rOut->b.size = 0; 1384 return EcDaa(rOut, sOut, curveId, dIn, digest, kIn); 1385 break; 1386 #endif 1387 #ifdef TPM_ALG_ECSCHNORR 1388 case TPM_ALG_ECSCHNORR: 1389 return SchnorrEcc(rOut, sOut, hashAlg, curveId, dIn, digest, kIn); 1390 break; 1391 #endif 1392 #ifdef TPM_ALG_SM2 1393 case TPM_ALG_SM2: 1394 return SignSM2(rOut, sOut, curveId, dIn, digest); 1395 break; 1396 #endif 1397 default: 1398 return CRYPT_SCHEME; 1399 } 1400 } 1401 #ifdef TPM_ALG_ECDSA //% 1402 // 1403 // 1404 // ValidateSignatureEcdsa() 1405 // 1406 // This function validates an ECDSA signature. rIn and sIn shoudl have been checked to make sure that 1407 // they are not zero. 1408 // 1409 // Return Value Meaning 1410 // 1411 // CRYPT_SUCCESS signature valid 1412 // CRYPT_FAIL signature not valid 1413 // 1414 static CRYPT_RESULT 1415 ValidateSignatureEcdsa( 1416 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature 1417 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature 1418 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 1419 // process 1420 TPMS_ECC_POINT *Qin, // IN: the public point of the key 1421 TPM2B *digest // IN: the digest that was signed 1422 ) 1423 { 1424 TPM2B_ECC_PARAMETER U1; 1425 TPM2B_ECC_PARAMETER U2; 1426 TPMS_ECC_POINT R; 1427 const TPM2B *n; 1428 BN_CTX *context; 1429 EC_POINT *pQ = NULL; 1430 EC_GROUP *group = NULL; 1431 BIGNUM *bnU1; 1432 BIGNUM *bnU2; 1433 BIGNUM *bnR; 1434 BIGNUM *bnS; 1435 BIGNUM *bnW; 1436 BIGNUM *bnV; 1437 BIGNUM *bnN; 1438 BIGNUM *bnE; 1439 BIGNUM *bnQx; 1440 BIGNUM *bnQy; 1441 CRYPT_RESULT retVal = CRYPT_FAIL; 1442 int t; 1443 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1444 // The curve selector should have been filtered by the unmarshaling process 1445 pAssert (curveData != NULL); 1446 n = curveData->n; 1447 // 1. If r and s are not both integers in the interval [1, n - 1], output 1448 // INVALID. 1449 // rIn and sIn are known to be greater than zero (was checked by the caller). 1450 if( _math__uComp(rIn->t.size, rIn->t.buffer, n->size, n->buffer) >= 0 1451 || _math__uComp(sIn->t.size, sIn->t.buffer, n->size, n->buffer) >= 0 1452 ) 1453 return CRYPT_FAIL; 1454 context = BN_CTX_new(); 1455 if(context == NULL) 1456 FAIL(FATAL_ERROR_ALLOCATION); 1457 BN_CTX_start(context); 1458 bnR = BN_CTX_get(context); 1459 bnS = BN_CTX_get(context); 1460 bnN = BN_CTX_get(context); 1461 bnE = BN_CTX_get(context); 1462 bnV = BN_CTX_get(context); 1463 bnW = BN_CTX_get(context); 1464 bnQx = BN_CTX_get(context); 1465 bnQy = BN_CTX_get(context); 1466 bnU1 = BN_CTX_get(context); 1467 bnU2 = BN_CTX_get(context); 1468 // Assume the size variables do not overflow, which should not happen in 1469 // the contexts that this function will be called. 1470 assert2Bsize(Qin->x.t); 1471 assert2Bsize(rIn->t); 1472 assert2Bsize(sIn->t); 1473 // BN_CTX_get() is sticky so only need to check the last value to know that 1474 // all worked. 1475 if( bnU2 == NULL 1476 // initialize the group parameters 1477 || (group = EccCurveInit(curveId, context)) == NULL 1478 // allocate a local point 1479 || (pQ = EC_POINT_new(group)) == NULL 1480 // use the public key values (QxIn and QyIn) to initialize Q 1481 || BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQx) == NULL 1482 || BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQy) == NULL 1483 || !EC_POINT_set_affine_coordinates_GFp(group, pQ, bnQx, bnQy, context) 1484 // convert the signature values 1485 || BN_bin2bn(rIn->t.buffer, rIn->t.size, bnR) == NULL 1486 || BN_bin2bn(sIn->t.buffer, sIn->t.size, bnS) == NULL 1487 // convert the curve order 1488 || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL) 1489 FAIL(FATAL_ERROR_INTERNAL); 1490 // 2. Use the selected hash function to compute H0 = Hash(M0). 1491 // This is an input parameter 1492 // 3. Convert the bit string H0 to an integer e as described in Appendix B.2. 1493 t = (digest->size > rIn->t.size) ? rIn->t.size : digest->size; 1494 if(BN_bin2bn(digest->buffer, t, bnE) == NULL) 1495 FAIL(FATAL_ERROR_INTERNAL); 1496 // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1. 1497 if (BN_mod_inverse(bnW, bnS, bnN, context) == NULL) 1498 FAIL(FATAL_ERROR_INTERNAL); 1499 // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n. 1500 if( !BN_mod_mul(bnU1, bnE, bnW, bnN, context) 1501 || !BN_mod_mul(bnU2, bnR, bnW, bnN, context)) 1502 FAIL(FATAL_ERROR_INTERNAL); 1503 BnTo2B(&U1.b, bnU1, (INT16) BN_num_bytes(bnU1)); 1504 BnTo2B(&U2.b, bnU2, (INT16) BN_num_bytes(bnU2)); 1505 // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC 1506 // scalar multiplication and EC addition (see [Routines]). If R is equal to 1507 // the point at infinity O, output INVALID. 1508 if(_cpri__EccPointMultiply(&R, curveId, &U1, Qin, &U2) == CRYPT_SUCCESS) 1509 { 1510 // 7. Compute v = Rx mod n. 1511 if( BN_bin2bn(R.x.t.buffer, R.x.t.size, bnV) == NULL 1512 || !BN_mod(bnV, bnV, bnN, context)) 1513 FAIL(FATAL_ERROR_INTERNAL); 1514 // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID 1515 if(BN_cmp(bnV, bnR) == 0) 1516 retVal = CRYPT_SUCCESS; 1517 } 1518 if(pQ != NULL) EC_POINT_free(pQ); 1519 if(group != NULL) EC_GROUP_free(group); 1520 BN_CTX_end(context); 1521 BN_CTX_free(context); 1522 return retVal; 1523 } 1524 #endif //% TPM_ALG_ECDSA 1525 #ifdef TPM_ALG_ECSCHNORR //% 1526 // 1527 // 1528 // ValidateSignatureEcSchnorr() 1529 // 1530 // This function is used to validate an EC Schnorr signature. rIn and sIn are required to be greater than 1531 // zero. This is checked in _cpri__ValidateSignatureEcc(). 1532 // 1533 // Return Value Meaning 1534 // 1535 // CRYPT_SUCCESS signature valid 1536 // CRYPT_FAIL signature not valid 1537 // CRYPT_SCHEME hashAlg is not supported 1538 // 1539 static CRYPT_RESULT 1540 ValidateSignatureEcSchnorr( 1541 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature 1542 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature 1543 TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature 1544 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 1545 // process 1546 TPMS_ECC_POINT *Qin, // IN: the public point of the key 1547 TPM2B *digest // IN: the digest that was signed 1548 ) 1549 { 1550 TPMS_ECC_POINT pE; 1551 const TPM2B *n; 1552 CPRI_HASH_STATE hashState; 1553 TPM2B_DIGEST rPrime; 1554 TPM2B_ECC_PARAMETER minusR; 1555 UINT16 digestSize = _cpri__GetDigestSize(hashAlg); 1556 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1557 // The curve parameter should have been filtered by unmarshaling code 1558 pAssert(curveData != NULL); 1559 if(digestSize == 0) 1560 return CRYPT_SCHEME; 1561 // Input parameter validation 1562 pAssert(rIn != NULL && sIn != NULL && Qin != NULL && digest != NULL); 1563 n = curveData->n; 1564 // if sIn or rIn are not between 1 and N-1, signature check fails 1565 // sIn and rIn were verified to be non-zero by the caller 1566 if( _math__uComp(sIn->b.size, sIn->b.buffer, n->size, n->buffer) >= 0 1567 || _math__uComp(rIn->b.size, rIn->b.buffer, n->size, n->buffer) >= 0 1568 ) 1569 return CRYPT_FAIL; 1570 //E = [s]InG - [r]InQ 1571 _math__sub(n->size, n->buffer, 1572 rIn->t.size, rIn->t.buffer, 1573 &minusR.t.size, minusR.t.buffer); 1574 if(_cpri__EccPointMultiply(&pE, curveId, sIn, Qin, &minusR) != CRYPT_SUCCESS) 1575 return CRYPT_FAIL; 1576 // Ex = Ex mod N 1577 if(Mod2B(&pE.x.b, n) != CRYPT_SUCCESS) 1578 FAIL(FATAL_ERROR_INTERNAL); 1579 _math__Normalize2B(&pE.x.b); 1580 // rPrime = h(digest || pE.x) mod n; 1581 _cpri__StartHash(hashAlg, FALSE, &hashState); 1582 _cpri__UpdateHash(&hashState, digest->size, digest->buffer); 1583 _cpri__UpdateHash(&hashState, pE.x.t.size, pE.x.t.buffer); 1584 if(_cpri__CompleteHash(&hashState, digestSize, rPrime.t.buffer) != digestSize) 1585 FAIL(FATAL_ERROR_INTERNAL); 1586 rPrime.t.size = digestSize; 1587 // rPrime = rPrime (mod n) 1588 if(Mod2B(&rPrime.b, n) != CRYPT_SUCCESS) 1589 FAIL(FATAL_ERROR_INTERNAL); 1590 // if the values don't match, then the signature is bad 1591 if(_math__uComp(rIn->t.size, rIn->t.buffer, 1592 rPrime.t.size, rPrime.t.buffer) != 0) 1593 return CRYPT_FAIL; 1594 else 1595 return CRYPT_SUCCESS; 1596 } 1597 #endif //% TPM_ALG_ECSCHNORR 1598 #ifdef TPM_ALG_SM2 //% 1599 // 1600 // 1601 // ValidateSignatueSM2Dsa() 1602 // 1603 // This function is used to validate an SM2 signature. 1604 // 1605 // Return Value Meaning 1606 // 1607 // CRYPT_SUCCESS signature valid 1608 // CRYPT_FAIL signature not valid 1609 // 1610 static CRYPT_RESULT 1611 ValidateSignatureSM2Dsa( 1612 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature 1613 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature 1614 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 1615 // process 1616 TPMS_ECC_POINT *Qin, // IN: the public point of the key 1617 TPM2B *digest // IN: the digest that was signed 1618 ) 1619 { 1620 BIGNUM *bnR; 1621 BIGNUM *bnRp; 1622 BIGNUM *bnT; 1623 BIGNUM *bnS; 1624 BIGNUM *bnE; 1625 BIGNUM *order; 1626 EC_POINT *pQ; 1627 BN_CTX *context; 1628 EC_GROUP *group = NULL; 1629 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1630 BOOL fail = FALSE; 1631 // 1632 if((context = BN_CTX_new()) == NULL || curveData == NULL) 1633 FAIL(FATAL_ERROR_INTERNAL); 1634 bnR = BN_CTX_get(context); 1635 bnRp= BN_CTX_get(context); 1636 bnE = BN_CTX_get(context); 1637 bnT = BN_CTX_get(context); 1638 bnS = BN_CTX_get(context); 1639 order = BN_CTX_get(context); 1640 if( order == NULL 1641 || (group = EccCurveInit(curveId, context)) == NULL) 1642 FAIL(FATAL_ERROR_INTERNAL); 1643 #ifdef _SM2_SIGN_DEBUG 1644 cpy_hexTo2B(&Qin->x.b, 1645 "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A"); 1646 cpy_hexTo2B(&Qin->y.b, 1647 "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"); 1648 cpy_hexTo2B(digest, 1649 "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76"); 1650 #endif 1651 pQ = EccInitPoint2B(group, Qin, context); 1652 #ifdef _SM2_SIGN_DEBUG 1653 pAssert(EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, bnS, context)); 1654 pAssert(cmp_bn2hex(bnT, 1655 "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A") 1656 == 0); 1657 pAssert(cmp_bn2hex(bnS, 1658 "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857") 1659 == 0); 1660 #endif 1661 BnFrom2B(bnR, &rIn->b); 1662 BnFrom2B(bnS, &sIn->b); 1663 BnFrom2B(bnE, digest); 1664 #ifdef _SM2_SIGN_DEBUG 1665 // Make sure that the input signature is the test signature 1666 pAssert(cmp_2B2hex(&rIn->b, 1667 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") == 0); 1668 pAssert(cmp_2B2hex(&sIn->b, 1669 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") == 0); 1670 #endif 1671 // a) verify that r and s are in the inclusive interval 1 to (n 1) 1672 if (!EC_GROUP_get_order(group, order, context)) goto Cleanup; 1673 fail = (BN_ucmp(bnR, order) >= 0); 1674 fail = (BN_ucmp(bnS, order) >= 0) || fail; 1675 if(fail) 1676 // There is no reason to continue. Since r and s are inputs from the caller, 1677 // they can know that the values are not in the proper range. So, exiting here 1678 // does not disclose any information. 1679 goto Cleanup; 1680 // b) compute t := (r + s) mod n 1681 if(!BN_mod_add(bnT, bnR, bnS, order, context)) 1682 FAIL(FATAL_ERROR_INTERNAL); 1683 #ifdef _SM2_SIGN_DEBUG 1684 pAssert(cmp_bn2hex(bnT, 1685 "2B75F07ED7ECE7CCC1C8986B991F441AD324D6D619FE06DD63ED32E0C997C801") 1686 == 0); 1687 #endif 1688 // c) verify that t > 0 1689 if(BN_is_zero(bnT)) { 1690 fail = TRUE; 1691 // set to a value that should allow rest of the computations to run without 1692 // trouble 1693 BN_copy(bnT, bnS); 1694 } 1695 // d) compute (x, y) := [s]G + [t]Q 1696 if(!EC_POINT_mul(group, pQ, bnS, pQ, bnT, context)) 1697 FAIL(FATAL_ERROR_INTERNAL); 1698 // Get the x coordinate of the point 1699 if(!EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, NULL, context)) 1700 FAIL(FATAL_ERROR_INTERNAL); 1701 #ifdef _SM2_SIGN_DEBUG 1702 pAssert(cmp_bn2hex(bnT, 1703 "110FCDA57615705D5E7B9324AC4B856D23E6D9188B2AE47759514657CE25D112") 1704 == 0); 1705 #endif 1706 // e) compute r' := (e + x) mod n (the x coordinate is in bnT) 1707 if(!BN_mod_add(bnRp, bnE, bnT, order, context)) 1708 FAIL(FATAL_ERROR_INTERNAL); 1709 // f) verify that r' = r 1710 fail = BN_ucmp(bnR, bnRp) != 0 || fail; 1711 Cleanup: 1712 if(pQ) EC_POINT_free(pQ); 1713 if(group) EC_GROUP_free(group); 1714 BN_CTX_end(context); 1715 BN_CTX_free(context); 1716 if(fail) 1717 return CRYPT_FAIL; 1718 else 1719 return CRYPT_SUCCESS; 1720 } 1721 #endif //% TPM_ALG_SM2 1722 // 1723 // 1724 // _cpri__ValidateSignatureEcc() 1725 // 1726 // This function validates 1727 // 1728 // Return Value Meaning 1729 // 1730 // CRYPT_SUCCESS signature is valid 1731 // CRYPT_FAIL not a valid signature 1732 // CRYPT_SCHEME unsupported scheme 1733 // 1734 LIB_EXPORT CRYPT_RESULT 1735 _cpri__ValidateSignatureEcc( 1736 TPM2B_ECC_PARAMETER *rIn, // IN: r component of the signature 1737 TPM2B_ECC_PARAMETER *sIn, // IN: s component of the signature 1738 TPM_ALG_ID scheme, // IN: the scheme selector 1739 TPM_ALG_ID hashAlg, // IN: the hash algorithm used (not used 1740 // in all schemes) 1741 TPM_ECC_CURVE curveId, // IN: the curve used in the signature 1742 // process 1743 TPMS_ECC_POINT *Qin, // IN: the public point of the key 1744 TPM2B *digest // IN: the digest that was signed 1745 ) 1746 { 1747 CRYPT_RESULT retVal; 1748 // return failure if either part of the signature is zero 1749 if(_math__Normalize2B(&rIn->b) == 0 || _math__Normalize2B(&sIn->b) == 0) 1750 return CRYPT_FAIL; 1751 switch (scheme) 1752 { 1753 case TPM_ALG_ECDSA: 1754 retVal = ValidateSignatureEcdsa(rIn, sIn, curveId, Qin, digest); 1755 break; 1756 #ifdef TPM_ALG_ECSCHNORR 1757 case TPM_ALG_ECSCHNORR: 1758 retVal = ValidateSignatureEcSchnorr(rIn, sIn, hashAlg, curveId, Qin, 1759 digest); 1760 break; 1761 #endif 1762 #ifdef TPM_ALG_SM2 1763 case TPM_ALG_SM2: 1764 retVal = ValidateSignatureSM2Dsa(rIn, sIn, curveId, Qin, digest); 1765 #endif 1766 default: 1767 retVal = CRYPT_SCHEME; 1768 break; 1769 } 1770 return retVal; 1771 } 1772 #if CC_ZGen_2Phase == YES //% 1773 #ifdef TPM_ALG_ECMQV 1774 // 1775 // 1776 // avf1() 1777 // 1778 // This function does the associated value computation required by MQV key exchange. Process: 1779 // a) Convert xQ to an integer xqi using the convention specified in Appendix C.3. 1780 // b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). 1781 // c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) 1782 // 1783 static BOOL 1784 avf1( 1785 BIGNUM *bnX, // IN/OUT: the reduced value 1786 BIGNUM *bnN // IN: the order of the curve 1787 ) 1788 { 1789 // compute f = 2^(ceil(ceil(log2(n)) / 2)) 1790 int f = (BN_num_bits(bnN) + 1) / 2; 1791 // x' = 2^f + (x mod 2^f) 1792 BN_mask_bits(bnX, f); // This is mod 2*2^f but it doesn't matter because 1793 // the next operation will SET the extra bit anyway 1794 BN_set_bit(bnX, f); 1795 return TRUE; 1796 } 1797 // 1798 // 1799 // C_2_2_MQV() 1800 // 1801 // This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC MQV). 1802 // CAUTION: Implementation of this function may require use of essential claims in patents not owned by 1803 // TCG members. 1804 // Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly 1805 // catastrophically, if this is not the case. 1806 // 1807 // 1808 // 1809 // Return Value Meaning 1810 // 1811 // CRYPT_SUCCESS results is valid 1812 // CRYPT_NO_RESULT the value for dsA does not give a valid point on the curve 1813 // 1814 static CRYPT_RESULT 1815 C_2_2_MQV( 1816 TPMS_ECC_POINT *outZ, // OUT: the computed point 1817 TPM_ECC_CURVE curveId, // IN: the curve for the computations 1818 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key 1819 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key 1820 TPMS_ECC_POINT *QsB, // IN: static public party B key 1821 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key 1822 ) 1823 { 1824 BN_CTX *context; 1825 EC_POINT *pQeA = NULL; 1826 EC_POINT *pQeB = NULL; 1827 EC_POINT *pQsB = NULL; 1828 EC_GROUP *group = NULL; 1829 BIGNUM *bnTa; 1830 BIGNUM *bnDeA; 1831 BIGNUM *bnDsA; 1832 BIGNUM *bnXeA; // x coordinate of ephemeral party A key 1833 BIGNUM *bnH; 1834 BIGNUM *bnN; 1835 BIGNUM *bnXeB; 1836 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1837 CRYPT_RESULT retVal; 1838 pAssert( curveData != NULL && outZ != NULL && dsA != NULL 1839 && deA != NULL && QsB != NULL && QeB != NULL); 1840 context = BN_CTX_new(); 1841 if(context == NULL || curveData == NULL) 1842 FAIL(FATAL_ERROR_ALLOCATION); 1843 BN_CTX_start(context); 1844 bnTa = BN_CTX_get(context); 1845 bnDeA = BN_CTX_get(context); 1846 bnDsA = BN_CTX_get(context); 1847 bnXeA = BN_CTX_get(context); 1848 bnH = BN_CTX_get(context); 1849 bnN = BN_CTX_get(context); 1850 bnXeB = BN_CTX_get(context); 1851 if(bnXeB == NULL) 1852 FAIL(FATAL_ERROR_ALLOCATION); 1853 // Process: 1854 // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. 1855 // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). 1856 // 3. If P = O, output an error indicator. 1857 // 4. Z=xP, where xP is the x-coordinate of P. 1858 // Initialize group parameters and local values of input 1859 if((group = EccCurveInit(curveId, context)) == NULL) 1860 FAIL(FATAL_ERROR_INTERNAL); 1861 if((pQeA = EC_POINT_new(group)) == NULL) 1862 FAIL(FATAL_ERROR_ALLOCATION); 1863 BnFrom2B(bnDeA, &deA->b); 1864 BnFrom2B(bnDsA, &dsA->b); 1865 BnFrom2B(bnH, curveData->h); 1866 BnFrom2B(bnN, curveData->n); 1867 BnFrom2B(bnXeB, &QeB->x.b); 1868 pQeB = EccInitPoint2B(group, QeB, context); 1869 pQsB = EccInitPoint2B(group, QsB, context); 1870 // Compute the public ephemeral key pQeA = [de,A]G 1871 if( (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context)) 1872 != CRYPT_SUCCESS) 1873 goto Cleanup; 1874 if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1) 1875 FAIL(FATAL_ERROR_INTERNAL); 1876 // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. 1877 // tA := (ds,A + de,A avf(Xe,A)) mod n (3) 1878 // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n 1879 // Ta = avf(XeA); 1880 BN_copy(bnTa, bnXeA); 1881 avf1(bnTa, bnN); 1882 if(// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n 1883 !BN_mod_mul(bnTa, bnDsA, bnTa, bnN, context) 1884 // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n 1885 || !BN_mod_add(bnTa, bnDeA, bnTa, bnN, context) 1886 ) 1887 FAIL(FATAL_ERROR_INTERNAL); 1888 // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). 1889 // Put this in because almost every case of h is == 1 so skip the call when 1890 // not necessary. 1891 if(!BN_is_one(bnH)) 1892 { 1893 // Cofactor is not 1 so compute Ta := Ta * h mod n 1894 if(!BN_mul(bnTa, bnTa, bnH, context)) 1895 FAIL(FATAL_ERROR_INTERNAL); 1896 } 1897 // Now that 'tA' is (h * 'tA' mod n) 1898 // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B). 1899 // first, compute XeB = avf(XeB) 1900 avf1(bnXeB, bnN); 1901 // QsB := [XeB]QsB 1902 if( !EC_POINT_mul(group, pQsB, NULL, pQsB, bnXeB, context) 1903 // QeB := QsB + QeB 1904 || !EC_POINT_add(group, pQeB, pQeB, pQsB, context) 1905 ) 1906 FAIL(FATAL_ERROR_INTERNAL); 1907 // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity 1908 if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS) 1909 // Convert BIGNUM E to TPM2B E 1910 Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context); 1911 Cleanup: 1912 if(pQeA != NULL) EC_POINT_free(pQeA); 1913 if(pQeB != NULL) EC_POINT_free(pQeB); 1914 if(pQsB != NULL) EC_POINT_free(pQsB); 1915 if(group != NULL) EC_GROUP_free(group); 1916 BN_CTX_end(context); 1917 BN_CTX_free(context); 1918 return retVal; 1919 } 1920 #endif // TPM_ALG_ECMQV 1921 #ifdef TPM_ALG_SM2 //% 1922 // 1923 // 1924 // avfSm2() 1925 // 1926 // This function does the associated value computation required by SM2 key exchange. This is different 1927 // form the avf() in the international standards because it returns a value that is half the size of the value 1928 // returned by the standard avf. For example, if n is 15, Ws (w in the standard) is 2 but the W here is 1. This 1929 // means that an input value of 14 (1110b) would return a value of 110b with the standard but 10b with the 1930 // scheme in SM2. 1931 // 1932 static BOOL 1933 avfSm2( 1934 BIGNUM *bnX, // IN/OUT: the reduced value 1935 BIGNUM *bnN // IN: the order of the curve 1936 ) 1937 { 1938 // a) set w := ceil(ceil(log2(n)) / 2) - 1 1939 int w = ((BN_num_bits(bnN) + 1) / 2) - 1; 1940 // b) set x' := 2^w + ( x & (2^w - 1)) 1941 // This is just like the avf for MQV where x' = 2^w + (x mod 2^w) 1942 BN_mask_bits(bnX, w); // as wiht avf1, this is too big by a factor of 2 but 1943 // it doesn't matter becasue we SET the extra bit anyway 1944 BN_set_bit(bnX, w); 1945 return TRUE; 1946 } 1947 // 1948 // SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to compute 1949 // tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA + 1950 // [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral private 1951 // key. All points are required to be on the curve of inQsA. The function will fail catastrophically if this is not 1952 // the case 1953 // 1954 // Return Value Meaning 1955 // 1956 // CRYPT_SUCCESS results is valid 1957 // CRYPT_NO_RESULT the value for dsA does not give a valid point on the curve 1958 // 1959 static CRYPT_RESULT 1960 SM2KeyExchange( 1961 TPMS_ECC_POINT *outZ, // OUT: the computed point 1962 TPM_ECC_CURVE curveId, // IN: the curve for the computations 1963 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key 1964 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key 1965 TPMS_ECC_POINT *QsB, // IN: static public party B key 1966 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key 1967 ) 1968 { 1969 BN_CTX *context; 1970 EC_POINT *pQeA = NULL; 1971 EC_POINT *pQeB = NULL; 1972 EC_POINT *pQsB = NULL; 1973 EC_GROUP *group = NULL; 1974 BIGNUM *bnTa; 1975 BIGNUM *bnDeA; 1976 BIGNUM *bnDsA; 1977 BIGNUM *bnXeA; // x coordinate of ephemeral party A key 1978 BIGNUM *bnH; 1979 BIGNUM *bnN; 1980 BIGNUM *bnXeB; 1981 // 1982 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 1983 CRYPT_RESULT retVal; 1984 pAssert( curveData != NULL && outZ != NULL && dsA != NULL 1985 && deA != NULL && QsB != NULL && QeB != NULL); 1986 context = BN_CTX_new(); 1987 if(context == NULL || curveData == NULL) 1988 FAIL(FATAL_ERROR_ALLOCATION); 1989 BN_CTX_start(context); 1990 bnTa = BN_CTX_get(context); 1991 bnDeA = BN_CTX_get(context); 1992 bnDsA = BN_CTX_get(context); 1993 bnXeA = BN_CTX_get(context); 1994 bnH = BN_CTX_get(context); 1995 bnN = BN_CTX_get(context); 1996 bnXeB = BN_CTX_get(context); 1997 if(bnXeB == NULL) 1998 FAIL(FATAL_ERROR_ALLOCATION); 1999 // Initialize group parameters and local values of input 2000 if((group = EccCurveInit(curveId, context)) == NULL) 2001 FAIL(FATAL_ERROR_INTERNAL); 2002 if((pQeA = EC_POINT_new(group)) == NULL) 2003 FAIL(FATAL_ERROR_ALLOCATION); 2004 BnFrom2B(bnDeA, &deA->b); 2005 BnFrom2B(bnDsA, &dsA->b); 2006 BnFrom2B(bnH, curveData->h); 2007 BnFrom2B(bnN, curveData->n); 2008 BnFrom2B(bnXeB, &QeB->x.b); 2009 pQeB = EccInitPoint2B(group, QeB, context); 2010 pQsB = EccInitPoint2B(group, QsB, context); 2011 // Compute the public ephemeral key pQeA = [de,A]G 2012 if( (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context)) 2013 != CRYPT_SUCCESS) 2014 goto Cleanup; 2015 if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1) 2016 FAIL(FATAL_ERROR_INTERNAL); 2017 // tA := (ds,A + de,A avf(Xe,A)) mod n (3) 2018 // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n 2019 // Ta = avf(XeA); 2020 BN_copy(bnTa, bnXeA); 2021 avfSm2(bnTa, bnN); 2022 if(// do Ta = de,A * Ta mod n = deA * avf(XeA) mod n 2023 !BN_mod_mul(bnTa, bnDeA, bnTa, bnN, context) 2024 // now Ta = dsA + Ta mod n = dsA + deA * avf(XeA) mod n 2025 || !BN_mod_add(bnTa, bnDsA, bnTa, bnN, context) 2026 ) 2027 FAIL(FATAL_ERROR_INTERNAL); 2028 // outZ ? [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4) 2029 // Put this in because almost every case of h is == 1 so skip the call when 2030 // not necessary. 2031 if(!BN_is_one(bnH)) 2032 { 2033 // Cofactor is not 1 so compute Ta := Ta * h mod n 2034 if(!BN_mul(bnTa, bnTa, bnH, context)) 2035 FAIL(FATAL_ERROR_INTERNAL); 2036 } 2037 // Now that 'tA' is (h * 'tA' mod n) 2038 // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)). 2039 // first, compute XeB = avf(XeB) 2040 avfSm2(bnXeB, bnN); 2041 // QeB := [XeB]QeB 2042 if( !EC_POINT_mul(group, pQeB, NULL, pQeB, bnXeB, context) 2043 // QeB := QsB + QeB 2044 || !EC_POINT_add(group, pQeB, pQeB, pQsB, context) 2045 ) 2046 FAIL(FATAL_ERROR_INTERNAL); 2047 // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity 2048 if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS) 2049 // Convert BIGNUM E to TPM2B E 2050 Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context); 2051 Cleanup: 2052 if(pQeA != NULL) EC_POINT_free(pQeA); 2053 if(pQeB != NULL) EC_POINT_free(pQeB); 2054 if(pQsB != NULL) EC_POINT_free(pQsB); 2055 if(group != NULL) EC_GROUP_free(group); 2056 BN_CTX_end(context); 2057 BN_CTX_free(context); 2058 return retVal; 2059 } 2060 #endif //% TPM_ALG_SM2 2061 // 2062 // 2063 // C_2_2_ECDH() 2064 // 2065 // This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified Model, 2066 // C(2, 2, ECC CDH). 2067 // 2068 static CRYPT_RESULT 2069 C_2_2_ECDH( 2070 TPMS_ECC_POINT *outZ1, // OUT: Zs 2071 TPMS_ECC_POINT *outZ2, // OUT: Ze 2072 TPM_ECC_CURVE curveId, // IN: the curve for the computations 2073 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key 2074 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key 2075 TPMS_ECC_POINT *QsB, // IN: static public party B key 2076 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key 2077 ) 2078 { 2079 BIGNUM *order; 2080 BN_CTX *context; 2081 EC_POINT *pQ = NULL; 2082 EC_GROUP *group = NULL; 2083 BIGNUM *bnD; 2084 INT16 size; 2085 const ECC_CURVE_DATA *curveData = GetCurveData(curveId); 2086 context = BN_CTX_new(); 2087 if(context == NULL || curveData == NULL) 2088 FAIL(FATAL_ERROR_ALLOCATION); 2089 BN_CTX_start(context); 2090 order = BN_CTX_get(context); 2091 if((bnD = BN_CTX_get(context)) == NULL) 2092 FAIL(FATAL_ERROR_INTERNAL); 2093 // Initialize group parameters and local values of input 2094 if((group = EccCurveInit(curveId, context)) == NULL) 2095 FAIL(FATAL_ERROR_INTERNAL); 2096 if (!EC_GROUP_get_order(group, order, context)) 2097 FAIL(FATAL_ERROR_INTERNAL); 2098 size = (INT16)BN_num_bytes(order); 2099 // Get the static private key of A 2100 BnFrom2B(bnD, &dsA->b); 2101 // Initialize the static public point from B 2102 pQ = EccInitPoint2B(group, QsB, context); 2103 // Do the point multiply for the Zs value 2104 if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT) 2105 // Convert the Zs value 2106 Point2B(group, outZ1, pQ, size, context); 2107 // Get the ephemeral private key of A 2108 BnFrom2B(bnD, &deA->b); 2109 // Initalize the ephemeral public point from B 2110 PointFrom2B(group, pQ, QeB, context); 2111 // Do the point multiply for the Ze value 2112 if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT) 2113 // Convert the Ze value. 2114 Point2B(group, outZ2, pQ, size, context); 2115 if(pQ != NULL) EC_POINT_free(pQ); 2116 if(group != NULL) EC_GROUP_free(group); 2117 BN_CTX_end(context); 2118 BN_CTX_free(context); 2119 return CRYPT_SUCCESS; 2120 } 2121 // 2122 // 2123 // _cpri__C_2_2_KeyExchange() 2124 // 2125 // This function is the dispatch routine for the EC key exchange function that use two ephemeral and two 2126 // static keys. 2127 // 2128 // Return Value Meaning 2129 // 2130 // CRYPT_SCHEME scheme is not defined 2131 // 2132 LIB_EXPORT CRYPT_RESULT 2133 _cpri__C_2_2_KeyExchange( 2134 TPMS_ECC_POINT *outZ1, // OUT: a computed point 2135 TPMS_ECC_POINT *outZ2, // OUT: and optional second point 2136 TPM_ECC_CURVE curveId, // IN: the curve for the computations 2137 TPM_ALG_ID scheme, // IN: the key exchange scheme 2138 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key 2139 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key 2140 TPMS_ECC_POINT *QsB, // IN: static public party B key 2141 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key 2142 ) 2143 { 2144 pAssert( outZ1 != NULL 2145 && dsA != NULL && deA != NULL 2146 && QsB != NULL && QeB != NULL); 2147 // Initalize the output points so that they are empty until one of the 2148 // functions decides otherwise 2149 outZ1->x.b.size = 0; 2150 outZ1->y.b.size = 0; 2151 if(outZ2 != NULL) 2152 { 2153 outZ2->x.b.size = 0; 2154 outZ2->y.b.size = 0; 2155 } 2156 switch (scheme) 2157 { 2158 case TPM_ALG_ECDH: 2159 return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB); 2160 break; 2161 #ifdef TPM_ALG_ECMQV 2162 case TPM_ALG_ECMQV: 2163 return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB); 2164 break; 2165 #endif 2166 #ifdef TPM_ALG_SM2 2167 case TPM_ALG_SM2: 2168 return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB); 2169 break; 2170 #endif 2171 default: 2172 return CRYPT_SCHEME; 2173 } 2174 } 2175 #else //% 2176 // 2177 // Stub used when the 2-phase key exchange is not defined so that the linker has something to associate 2178 // with the value in the .def file. 2179 // 2180 LIB_EXPORT CRYPT_RESULT 2181 _cpri__C_2_2_KeyExchange( 2182 void 2183 ) 2184 { 2185 return CRYPT_FAIL; 2186 } 2187 #endif //% CC_ZGen_2Phase 2188 #endif // TPM_ALG_ECC 2189