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