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