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// 25LIB_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// 40LIB_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} 49LIB_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// 72LIB_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} 87static const ECC_CURVE_DATA * 88GetCurveData( 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// 101static BOOL 102Point2B( 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// 140static EC_GROUP * 141EccCurveInit( 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 ); 189Cleanup: 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// 207static EC_POINT * 208PointFrom2B( 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// 240static EC_POINT * 241EccInitPoint2B( 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// 266static CRYPT_RESULT 267PointMul( 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// 291static void 292GetRandomPrivate( 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// 340LIB_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// 432static void 433ClearPoint2B( 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// 461LIB_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 } 563Cleanup: 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); 570Cleanup2: 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// 589LIB_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// 663LIB_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// 759LIB_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// 791LIB_EXPORT CRYPT_RESULT 792SignEcdsa( 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// 948static CRYPT_RESULT 949EcDaa( 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// 1021static CRYPT_RESULT 1022Mod2B( 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// 1061static CRYPT_RESULT 1062SchnorrEcc( 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 //% 1173static int 1174cmp_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} 1187static int 1188cmp_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} 1204static void 1205cpy_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// 1234static CRYPT_RESULT 1235SignSM2( 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 1272BN_hex2bn(&bnE, "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76"); 1273BN_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; 1278loop: 1279 { 1280 // Get a random number 1281 _cpri__GenerateRandom(k.t.size, k.t.buffer); 1282#ifdef _SM2_SIGN_DEBUG 1283BN_hex2bn(&bnK, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F"); 1284BnTo2B(&k.b,bnK, 32); 1285k.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 1303pAssert(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 1320pAssert(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 1330pAssert(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 1342pAssert(cmp_2B2hex(&rOut->b, 1343 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") 1344 == 0); 1345pAssert(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// 1364LIB_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// 1417static CRYPT_RESULT 1418ValidateSignatureEcdsa( 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// 1542static CRYPT_RESULT 1543ValidateSignatureEcSchnorr( 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// 1613static CRYPT_RESULT 1614ValidateSignatureSM2Dsa( 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 1669pAssert(cmp_2B2hex(&rIn->b, 1670 "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") == 0); 1671pAssert(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; 1714Cleanup: 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// 1737LIB_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// 1786static BOOL 1787avf1( 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// 1817static CRYPT_RESULT 1818C_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); 1914Cleanup: 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// 1935static BOOL 1936avfSm2( 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// 1962static CRYPT_RESULT 1963SM2KeyExchange( 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); 2054Cleanup: 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// 2071static CRYPT_RESULT 2072C_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// 2135LIB_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// 2183LIB_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