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