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