15679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// This file was extracted from the TCG Published
25679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Trusted Platform Module Library
35679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Part 4: Supporting Routines
45679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Family "2.0"
55679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Level 00 Revision 01.16
65679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// October 30, 2014
75679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
80a05071eda743000b3936bae53374bbe07893848Vadim Bendebury#include <string.h>
90a05071eda743000b3936bae53374bbe07893848Vadim Bendebury
105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include   "OsslCryptoEngine.h"
110a05071eda743000b3936bae53374bbe07893848Vadim Bendebury
125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECC
135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include   "CpriDataEcc.h"
145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include   "CpriDataEcc.c"
155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Functions
185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      _cpri__EccStartup()
205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     This function is called at TPM Startup to initialize the crypto units.
225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     In this implementation, no initialization is performed at startup but a future version may initialize the self-
235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     test functions here.
245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
255679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT BOOL
265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccStartup(
275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    void
285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return TRUE;
315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      _cpri__GetCurveIdByIndex()
355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     This function returns the number of the i-th implemented curve. The normal use would be to call this
375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     function with i starting at 0. When the i is greater than or equal to the number of implemented curves,
385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_ECC_NONE is returned.
395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
405679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT TPM_ECC_CURVE
415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__GetCurveIdByIndex(
425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                i
435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(i >= ECC_CURVE_COUNT)
465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return TPM_ECC_NONE;
475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return eccCurves[i].curveId;
485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
495679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT UINT32
505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccGetCurveCount(
515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    void
525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return ECC_CURVE_COUNT;
555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      _cpri__EccGetParametersByCurveId()
595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     This function returns a pointer to the curve data that is associated with the indicated curveId. If there is no
615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     curve with the indicated ID, the function returns NULL.
625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Return Value                      Meaning
675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     NULL                              curve with the      indicated   TPM_ECC_CURVE    value   is   not
695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                       implemented
705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     non-NULL                          pointer to the curve data
715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
725679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT const ECC_CURVE *
735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccGetParametersByCurveId(
745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE       curveId               // IN: the curveID
755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int          i;
785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   for(i = 0; i < ECC_CURVE_COUNT; i++)
795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(eccCurves[i].curveId == curveId)
815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return &eccCurves[i];
825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   FAIL(FATAL_ERROR_INTERNAL);
840a05071eda743000b3936bae53374bbe07893848Vadim Bendebury
850a05071eda743000b3936bae53374bbe07893848Vadim Bendebury   return NULL; // Never reached.
865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
875679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic const ECC_CURVE_DATA *
885679752bf24c21135884e987c4077e2f7184897Vadim BendeburyGetCurveData(
895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE       curveId               // IN: the curveID
905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE     *curve = _cpri__EccGetParametersByCurveId(curveId);
935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return curve->curveData;
945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Point2B()
985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     This function makes a TPMS_ECC_POINT from a BIGNUM EC_POINT.
1005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1015679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic BOOL
1025679752bf24c21135884e987c4077e2f7184897Vadim BendeburyPoint2B(
1035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP           *group,                //   IN: group for the point
1045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT     *p,                    //   OUT: receives the converted point
1055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT           *ecP,                  //   IN: the point to convert
1065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT16               size,                 //   IN: size of the coordinates
1075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX             *context               //   IN: working context
1085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
1095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
1105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM             *bnX;
1115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM             *bnY;
1125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
1135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnX = BN_CTX_get(context);
1145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnY = BN_CTX_get(context);
1155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(        bnY == NULL
1165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Get the coordinate values
1175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || EC_POINT_get_affine_coordinates_GFp(group, ecP, bnX, bnY, context) != 1
1185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert x
1195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || (!BnTo2B(&p->x.b, bnX, size))
1205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert y
1215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || (!BnTo2B(&p->y.b, bnY, size))
1225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
1235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
1245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
1255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TRUE;
1265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
1275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       EccCurveInit()
1305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function initializes the OpenSSL() group definition structure
1325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function is only used within this file.
1335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is a fatal error if groupContext is not provided.
1345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                       Meaning
1365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      NULL                               the TPM_ECC_CURVE is not valid
1385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      non-NULL                           points to a structure in groupContext static EC_GROUP *
1395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1405679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic EC_GROUP *
1415679752bf24c21135884e987c4077e2f7184897Vadim BendeburyEccCurveInit(
1425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE         curveId,             // IN: the ID of the curve
1435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX               *groupContext         // IN: the context in which the group is to be
1445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //     created
1455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
1465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
1475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const ECC_CURVE_DATA            *curveData = GetCurveData(curveId);
1485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_GROUP                        *group = NULL;
1495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT                        *P = NULL;
1505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                          *context;
1515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnP;
1525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnA;
1535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnB;
1545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnX;
1555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnY;
1565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnN;
1575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                          *bnH;
1585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    int                              ok = FALSE;
1595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Context must be provided and curve selector must be valid
1605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(groupContext != NULL && curveData != NULL);
1615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    context = BN_CTX_new();
1625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(context == NULL)
1635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
1645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_start(context);
1655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnP = BN_CTX_get(context);
1665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnA = BN_CTX_get(context);
1675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnB = BN_CTX_get(context);
1685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnX = BN_CTX_get(context);
1695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnY = BN_CTX_get(context);
1705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnN = BN_CTX_get(context);
1715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnH = BN_CTX_get(context);
1725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if (bnH == NULL)
1735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        goto Cleanup;
1745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Convert the number formats
1755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnP,      curveData->p);
1765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnA,      curveData->a);
1775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnB,      curveData->b);
1785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnX,      curveData->x);
1795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnY,      curveData->y);
1805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnN,      curveData->n);
1815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnH,      curveData->h);
1825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // initialize EC group, associate a generator point and initialize the point
1835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // from the parameter data
1845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   ok = (   (group = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, groupContext)) != NULL
1855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         && (P = EC_POINT_new(group)) != NULL
1865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         && EC_POINT_set_affine_coordinates_GFp(group, P, bnX, bnY, groupContext)
1875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         && EC_GROUP_set_generator(group, P, bnN, bnH)
1885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        );
1895679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup:
1905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if (!ok && group != NULL)
1915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
1925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       EC_GROUP_free(group);
1935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       group = NULL;
1945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
1955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(P != NULL)
1965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       EC_POINT_free(P);
1975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
1985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
1995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return group;
2005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       PointFrom2B()
2045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function sets the coordinates of an existing BN Point from a TPMS_ECC_POINT.
2065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2075679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic EC_POINT *
2085679752bf24c21135884e987c4077e2f7184897Vadim BendeburyPointFrom2B(
2095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP           *group,           //   IN:   the group for the point
2105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT           *ecP,             //   IN:   an existing BN point in the group
2115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT     *p,               //   IN:   the 2B coordinates of the point
2125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX             *context          //   IN:   the BIGNUM context
2135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
2145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM             *bnX;
2165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM             *bnY;
2175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If the point is not allocated then just return a NULL
2185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(ecP == NULL)
2195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return NULL;
2205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
2215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnX = BN_CTX_get(context);
2225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnY = BN_CTX_get(context);
2235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if( // Set the coordinates of the point
2245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         bnY == NULL
2255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(p->x.t.buffer, p->x.t.size, bnX) == NULL
2265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(p->y.t.buffer, p->y.t.size, bnY) == NULL
2275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || !EC_POINT_set_affine_coordinates_GFp(group, ecP, bnX, bnY, context)
2285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
2295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      FAIL(FATAL_ERROR_INTERNAL);
2305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
2315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return ecP;
2325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       EccInitPoint2B()
2365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function allocates a point in the provided group and initializes it with the values in a
2385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPMS_ECC_POINT.
2395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2405679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic EC_POINT *
2415679752bf24c21135884e987c4077e2f7184897Vadim BendeburyEccInitPoint2B(
2425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP           *group,           // IN: group for the point
2435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT     *p,               // IN: the coordinates for the point
2445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX              *context                // IN: the BIGNUM context
2455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT            *ecP;
2485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_start(context);
2495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    ecP = EC_POINT_new(group);
2505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(PointFrom2B(group, ecP, p, context) == NULL)
2515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_INTERNAL);
2525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_end(context);
2535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return ecP;
2545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       PointMul()
2585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function does a point multiply and checks for the result being the point at infinity. Q = ([A]G + [B]P)
2605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                      Meaning
2625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_NO_RESULT                   point is at infinity
2645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SUCCESS                     point not at infinity
2655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2665679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
2675679752bf24c21135884e987c4077e2f7184897Vadim BendeburyPointMul(
2685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_GROUP            *group,                 //      IN: group curve
2695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT            *ecpQ,                  //      OUT: result
2705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM              *bnA,                   //      IN: scalar for [A]G
2715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT            *ecpP,                  //      IN: point for [B]P
2725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM              *bnB,                   //      IN: scalar for [B]P
2735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX              *context                //      IN: working context
2745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(EC_POINT_mul(group, ecpQ, bnA, ecpP, bnB, context) != 1)
2775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
2785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(EC_POINT_is_at_infinity(group, ecpQ))
2795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return CRYPT_NO_RESULT;
2805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return CRYPT_SUCCESS;
2815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       GetRandomPrivate()
2855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function gets a random value (d) to use as a private ECC key and then qualifies the key so that it is
2875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      between 0 < d < n.
2885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      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
2895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      (the largest buffer size of a TPM2B_ECC_PARAMETER)
2905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2915679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
2925679752bf24c21135884e987c4077e2f7184897Vadim BendeburyGetRandomPrivate(
2935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER            *dOut,                    // OUT: the qualified random value
2945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const TPM2B                    *pIn                      // IN: the maximum value for the key
2955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    int             i;
2985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE           *pb;
2995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(pIn != NULL && dOut != NULL && pIn->size <= MAX_ECC_KEY_BYTES);
3005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Set the size of the output
3015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    dOut->t.size = pIn->size;
3025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Get some random bits
3035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    while(TRUE)
3045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
3055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        _cpri__GenerateRandom(dOut->t.size, dOut->t.buffer);
3065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // See if the d < n
3075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(memcmp(dOut->t.buffer, pIn->buffer, pIn->size) < 0)
3085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
3095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // dOut < n so make sure that 0 < dOut
3105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            for(pb = dOut->t.buffer, i = dOut->t.size; i > 0; i--)
3115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            {
3125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                if(*pb++ != 0)
3135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                    return;
3145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            }
3155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
3165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
3175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
3185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       _cpri__EccPointMultiply
3215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are points on
3235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      the specified curve and G is the default generator of the curve.
3245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      The xOut and yOut parameters are optional and may be set to NULL if not used.
3255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be provided. If dIn and
3265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      QIn are specified but uIn is not provided, then R = [dIn]QIn.
3275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      If the multiply produces the point at infinity, the CRYPT_NO_RESULT is returned.
3285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      The sizes of xOut and yOut' will be set to be the size of the degree of the curve
3295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is unspecified.
3305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                    Meaning
3355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SUCCESS                   point multiplication succeeded
3375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_POINT                     the point Qin is not on the curve
3385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_NO_RESULT                 the product point is at infinity
3395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3405679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
3415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccPointMultiply(
3425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *Rout,                  //   OUT: the product point R
3435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                  curveId,               //   IN: the curve to use
3445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *dIn,                   //   IN: value to multiply against the
3455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                         //       curve generator
3465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *Qin,                   //   IN: point Q
3475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *uIn                    //   IN: scalar value for the multiplier
3485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                         //       of Q
3495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
3505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
3515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                    *context;
3525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                    *bnD;
3535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                    *bnU;
3545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                  *group;
3555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                  *R = NULL;
3565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                  *Q = NULL;
3575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CRYPT_RESULT               retVal = CRYPT_SUCCESS;
3585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Validate that the required parameters are provided.
3595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert((dIn != NULL || uIn != NULL) && (Qin != NULL || dIn != NULL));
3605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If a point is provided for the multiply, make sure that it is on the curve
3615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(Qin != NULL && !_cpri__EccIsPointOnCurve(curveId, Qin))
3625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_POINT;
3635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
3645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL)
3655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
3665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
3675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnU = BN_CTX_get(context);
3685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnD = BN_CTX_get(context);
3695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   group = EccCurveInit(curveId, context);
3705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // There should be no path for getting a bad curve ID into this function.
3715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(group != NULL);
3725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // check allocations should have worked and allocate R
3735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   bnD == NULL
3745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || (R = EC_POINT_new(group)) == NULL)
3755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
3765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If Qin is present, create the point
3775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(Qin != NULL)
3785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
3795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Assume the size variables do not overflow. This should not happen in
3805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // the contexts in which this function will be called.
3815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       assert2Bsize(Qin->x.t);
3825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       assert2Bsize(Qin->x.t);
3835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Q = EccInitPoint2B(group, Qin, context);
3845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
3855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(dIn != NULL)
3865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
3875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Assume the size variables do not overflow, which should not happen in
3885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // the contexts that this function will be called.
3895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       assert2Bsize(dIn->t);
3905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BnFrom2B(bnD, &dIn->b);
3915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
3925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
3935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        bnD = NULL;
3945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If uIn is specified, initialize its BIGNUM
3955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(uIn != NULL)
3965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
3975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Assume the size variables do not overflow, which should not happen in
3985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // the contexts that this function will be called.
3995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        assert2Bsize(uIn->t);
4005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BnFrom2B(bnU, &uIn->b);
4015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
4025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If uIn is not specified but Q is, then we are going to
4035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // do R = [d]Q
4045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else if(Qin != NULL)
4055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
4065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        bnU = bnD;
4075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        bnD = NULL;
4085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
4095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If neither Q nor u is specified, then null this pointer
4105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
4115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        bnU = NULL;
4125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Use the generator of the curve
4135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if((retVal = PointMul(group, R, bnD, Q, bnU, context)) == CRYPT_SUCCESS)
414ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr        Point2B(group, Rout, R, (INT16) ((EC_GROUP_get_degree(group)+7)/8), context);
4155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if (Q)
4165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        EC_POINT_free(Q);
4175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(R)
4185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        EC_POINT_free(R);
4195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(group)
4205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        EC_GROUP_free(group);
4215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_end(context);
4225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_free(context);
4235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return retVal;
4245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
42516e65be1bdf7ee570373449d8cff729c55fc8776nagendra modadugu#if defined TPM_ALG_ECDAA || defined TPM_ALG_SM2 //%
4265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       ClearPoint2B()
4295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Initialize the size values of a point
4315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4325679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
4335679752bf24c21135884e987c4077e2f7184897Vadim BendeburyClearPoint2B(
4345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT       *p                 // IN: the point
4355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
4365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
4375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(p != NULL) {
4385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        p->x.t.size = 0;
4395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        p->y.t.size = 0;
4405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
4415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
4425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       _cpri__EccCommitCompute()
4455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function performs the point multiply operations required by TPM2_Commit().
4475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      If B or M is provided, they must be on the curve defined by curveId. This routine does not check that they
4485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      are on the curve and results are unpredictable if they are not.
4495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      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
4535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      not NULL, then it is a fatal error if E is NULL.
4545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                       Meaning
4565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SUCCESS                      computations completed normally
4585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_NO_RESULT                    if K, L or E was computed to be the point at infinity
4595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_CANCEL                       a cancel indication was asserted during this function
4605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4615679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
4625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccCommitCompute(
4635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                  *K,                   //   OUT: [d]B or [r]Q
4645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                  *L,                   //   OUT: [r]B
4655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                  *E,                   //   OUT: [r]M
4665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE                    curveId,             //   IN: the curve for the computations
4675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                  *M,                   //   IN: M (optional)
4685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                  *B,                   //   IN: B (optional)
4695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER             *d,                   //   IN: d (required)
4705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER             *r                    //   IN: the computed r value (required)
4715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
4725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
4735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                    *context;
4740a05071eda743000b3936bae53374bbe07893848Vadim Bendebury    BIGNUM                    *bnY, *bnR, *bnD;
4755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_GROUP                  *group;
4765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT                  *pK = NULL, *pL = NULL, *pE = NULL, *pM = NULL, *pB = NULL;
4775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                     keySizeInBytes;
4785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CRYPT_RESULT               retVal = CRYPT_SUCCESS;
4795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Validate that the required parameters are provided.
4805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do
4815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // E := [r]Q if both M and B are NULL.
4820a05071eda743000b3936bae53374bbe07893848Vadim Bendebury
4830a05071eda743000b3936bae53374bbe07893848Vadim Bendebury    pAssert((r && (K || !B) && (L || !B)) || (E || (!M && B)));
4845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    context = BN_CTX_new();
4855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(context == NULL)
4865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
4875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_start(context);
4885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnR = BN_CTX_get(context);
4895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnD = BN_CTX_get(context);
4905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnY = BN_CTX_get(context);
4915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(bnY == NULL)
4925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
4935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Initialize the output points in case they are not computed
4945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    ClearPoint2B(K);
4955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    ClearPoint2B(L);
4965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    ClearPoint2B(E);
4975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if((group = EccCurveInit(curveId, context)) == NULL)
4985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
4995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        retVal = CRYPT_PARAMETER;
5005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        goto Cleanup2;
5015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
502ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr    keySizeInBytes = (UINT16) ((EC_GROUP_get_degree(group)+7)/8);
503d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu    // Size of the r parameter may not be zero
504d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu    pAssert((int) r->t.size > 0);
5055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Convert scalars to BIGNUM
5065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BnFrom2B(bnR, &r->b);
5075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If B is provided, compute K=[d]B and L=[r]B
5085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(B != NULL)
5095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
510d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu       // Size of the d parameter may not be zero
511d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu       pAssert((int) d->t.size > 0);
512d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu       BnFrom2B(bnD, &d->b);
513d0a96517e517e9a2f3012910ffa1300973616070nagendra modadugu
5145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Allocate the points to receive the value
5155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(    (pK = EC_POINT_new(group)) == NULL
5165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || (pL = EC_POINT_new(group)) == NULL)
5175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
5185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // need to compute K = [d]B
5195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Allocate and initialize BIGNUM version of B
5205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       pB = EccInitPoint2B(group, B, context);
5215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // do the math for K = [d]B
5225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if((retVal = PointMul(group, pK, NULL, pB, bnD, context)) != CRYPT_SUCCESS)
5235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto Cleanup;
5245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Convert BN K to TPM2B K
5255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        Point2B(group, K, pK, (INT16)keySizeInBytes, context);
5265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // compute L= [r]B after checking for cancel
5275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(_plat__IsCanceled())
5285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
5295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            retVal = CRYPT_CANCEL;
5305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto Cleanup;
5315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
5325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // compute L = [r]B
5335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if((retVal = PointMul(group, pL, NULL, pB, bnR, context)) != CRYPT_SUCCESS)
5345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto Cleanup;
5355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Convert BN L to TPM2B L
5365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        Point2B(group, L, pL, (INT16)keySizeInBytes, context);
5375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
5385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(M != NULL || B == NULL)
5395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
5405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // if this is the third point multiply, check for cancel first
5415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(B != NULL && _plat__IsCanceled())
5425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
5435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           retVal = CRYPT_CANCEL;
5445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           goto Cleanup;
5455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       }
5465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Allocate E
5475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if((pE = EC_POINT_new(group)) == NULL)
5485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_ALLOCATION);
5495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Create BIGNUM version of M unless M is NULL
5505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(M != NULL)
5515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
5525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // M provided so initialize a BIGNUM M and compute E = [r]M
5535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             pM = EccInitPoint2B(group, M, context);
5545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             retVal = PointMul(group, pE, NULL, pM, bnR, context);
5555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
5565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        else
5575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // compute E = [r]G (this is only done if M and B are both NULL
5585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             retVal = PointMul(group, pE, bnR, NULL, NULL, context);
5595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(retVal == CRYPT_SUCCESS)
5605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // Convert E to 2B format
5615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            Point2B(group, E, pE, (INT16)keySizeInBytes, context);
5625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
5635679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup:
5645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP_free(group);
5655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pK != NULL) EC_POINT_free(pK);
5665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pL != NULL) EC_POINT_free(pL);
5675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pE != NULL) EC_POINT_free(pE);
5685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pM != NULL) EC_POINT_free(pM);
5695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pB != NULL) EC_POINT_free(pB);
5705679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup2:
5715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
5725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
5735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
5745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
5755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //%
5765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       _cpri__EccIsPointOnCurve()
5795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      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
5815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      + a*x + b mod p
5825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is a fatal error if Q is not specified (is NULL).
5835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                        Meaning
5855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TRUE                                point is on curve
5875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      FALSE                               point is not on curve or curve is not supported
5885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5895679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT BOOL
5905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__EccIsPointOnCurve(
5915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE          curveId,             // IN: the curve selector
5925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT        *Q                    // IN: the point.
5935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
5945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
5955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                           *context;
5965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bnX;
5975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bnY;
5985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bnA;
5995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bnB;
6005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bnP;
6015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                           *bn3;
6025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const ECC_CURVE_DATA             *curveData = GetCurveData(curveId);
6035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BOOL                              retVal;
6045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(Q != NULL && curveData != NULL);
6055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if((context = BN_CTX_new()) == NULL)
6065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
6075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_start(context);
6085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnX = BN_CTX_get(context);
6095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnY = BN_CTX_get(context);
6105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnA = BN_CTX_get(context);
6115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnB = BN_CTX_get(context);
6125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bn3 = BN_CTX_get(context);
6135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnP = BN_CTX_get(context);
6145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(bnP == NULL)
6155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
6165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Convert values
6175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if (    !BN_bin2bn(Q->x.t.buffer, Q->x.t.size, bnX)
6185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_bin2bn(Q->y.t.buffer, Q->y.t.size, bnY)
6195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_bin2bn(curveData->p->buffer, curveData->p->size, bnP)
6205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_bin2bn(curveData->a->buffer, curveData->a->size, bnA)
6215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_set_word(bn3, 3)
6225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_bin2bn(curveData->b->buffer, curveData->b->size, bnB)
6235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       )
6245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         FAIL(FATAL_ERROR_INTERNAL);
6255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // The following sequence is probably not optimal but it seems to be correct.
6265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // compute x^3 + a*x + b mod p
6275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // first, compute a*x mod p
6285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(   !BN_mod_mul(bnA, bnA, bnX, bnP, context)
6295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // next, compute a*x + b mod p
6315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_mod_add(bnA, bnA, bnB, bnP, context)
6325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // next, compute X^3 mod p
6335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_mod_exp(bnX, bnX, bn3, bnP, context)
6345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // finally, compute x^3 + a*x + b mod p
6355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_mod_add(bnX, bnX, bnA, bnP, context)
6365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // then compute y^2
6375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !BN_mod_mul(bnY, bnY, bnY, bnP, context)
6385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        )
6395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          FAIL(FATAL_ERROR_INTERNAL);
6405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    retVal = BN_cmp(bnX, bnY) == 0;
6415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_end(context);
6425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_free(context);
6435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return retVal;
6445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
6455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       _cpri__GenerateKeyEcc()
6485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function generates an ECC key pair based on the input parameters. This routine uses KDFa() to
6505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      produce candidate numbers. The method is according to FIPS 186-3, section B.4.1 "GKey() Pair
6515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Generation Using Extra Random Bits." According to the method in FIPS 186-3, the resulting private value
6525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      d should be 1 <= d < n where n is the order of the base point. In this implementation, the range of the
6535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      private value is further restricted to be 2^(nLen/2) <= d < n where nLen is the order of n.
6545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      EXAMPLE:         If the curve is NIST-P256, then nLen is 256 bits and d will need to be between 2^128 <= d < n
6565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is a fatal error if Qout, dOut, or seed is not provided (is NULL).
6585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                         Meaning
6605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_PARAMETER                      the hash algorithm is not supported
6625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6635679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
6645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__GenerateKeyEcc(
6655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                    *Qout,                  //   OUT: the public point
6665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER               *dOut,                  //   OUT: the private scalar
6675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE                      curveId,               //   IN: the curve identifier
6685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID                         hashAlg,               //   IN: hash algorithm to use in the key
6695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                              //       generation process
6705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B                             *seed,                  //   IN: the seed to use
6715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const char                        *label,                 //   IN: A label for the generation
6725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                              //       process.
6735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B                             *extra,                 //   IN: Party 1 data for the KDF
6745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT32                            *counter                //   IN/OUT: Counter value to allow KDF
6755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                              //       iteration to be propagated across
6765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                              //       multiple functions
6775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
6785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
6795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const ECC_CURVE_DATA              *curveData = GetCurveData(curveId);
6805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    INT16                              keySizeInBytes;
6815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT32                             count = 0;
6825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CRYPT_RESULT                       retVal;
6835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                             hLen = _cpri__GetDigestSize(hashAlg);
6845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                            *bnNm1;          // Order of the curve minus one
6855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                            *bnD;            // the private scalar
6865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                            *context;        // the context for the BIGNUM values
6875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                               withExtra[MAX_ECC_KEY_BYTES + 8]; // trial key with
6885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                                           //extra bits
6890a05071eda743000b3936bae53374bbe07893848Vadim Bendebury    TPM2B_4_BYTE_VALUE                 marshaledCounter = {.t = {4}};
6905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT32                             totalBits;
6915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Validate parameters (these are fatal)
6925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(     seed != NULL && dOut != NULL && Qout != NULL && curveData != NULL);
6935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Non-fatal parameter checks.
6945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(hLen <= 0)
6955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_PARAMETER;
6965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // allocate the local BN values
6975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
6985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL)
6995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
7005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
7015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnNm1 = BN_CTX_get(context);
7025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnD = BN_CTX_get(context);
7035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The size of the input scalars is limited by the size of the size of a
7045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // TPM2B_ECC_PARAMETER. Make sure that it is not irrational.
7055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert((int) curveData->n->size <= MAX_ECC_KEY_BYTES);
7065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   bnD == NULL
7075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnNm1) == NULL
7085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || (keySizeInBytes = (INT16) BN_num_bytes(bnNm1)) > MAX_ECC_KEY_BYTES)
7095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
7105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // get the total number of bits
7115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   totalBits = BN_num_bits(bnNm1) + 64;
7125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Reduce bnNm1 from 'n' to 'n' - 1
7135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_sub_word(bnNm1, 1);
7145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initialize the count value
7155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(counter != NULL)
7165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       count = *counter;
7175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(count == 0)
7185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       count = 1;
7195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Start search for key (should be quick)
7205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   for(; count != 0; count++)
7215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
7225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        UINT32_TO_BYTE_ARRAY(count, marshaledCounter.t.buffer);
7235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        _cpri__KDFa(hashAlg, seed, label, extra, &marshaledCounter.b,
7245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                    totalBits, withExtra, NULL, FALSE);
7255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Convert the result and modular reduce
7265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Assume the size variables do not overflow, which should not happen in
7275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // the contexts that this function will be called.
7285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        pAssert(keySizeInBytes <= MAX_ECC_KEY_BYTES);
7295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if (    BN_bin2bn(withExtra, keySizeInBytes+8, bnD) == NULL
7305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             || BN_mod(bnD, bnD, bnNm1, context) != 1)
7315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             FAIL(FATAL_ERROR_INTERNAL);
7325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Add one to get 0 < d < n
7335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BN_add_word(bnD, 1);
7345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(BnTo2B(&dOut->b, bnD, keySizeInBytes) != 1)
7355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                FAIL(FATAL_ERROR_INTERNAL);
7365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Do the point multiply to create the public portion of the key. If
7375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // the multiply generates the point at infinity (unlikely), do another
7385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // iteration.
7395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(    (retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL))
7405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            != CRYPT_NO_RESULT)
7415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            break;
7425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
7435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(count == 0) // if counter wrapped, then the TPM should go into failure mode
7445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
7455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Free up allocated BN values
7465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
7475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
7485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(counter != NULL)
7495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       *counter = count;
7505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
7515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
7525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       _cpri__GetEphemeralEcc()
7555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the
7575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      key will be discarded
7585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7595679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
7605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__GetEphemeralEcc(
7615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *Qout,            // OUT: the public point
7625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *dOut,            // OUT: the private scalar
7635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                  curveId          // IN: the curve for the key
7645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
7655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
7665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CRYPT_RESULT                   retVal;
7675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA          *curveData = GetCurveData(curveId);
7685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(curveData != NULL);
7695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Keep getting random values until one is found that doesn't create a point
7705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // at infinity. This will never, ever, ever, ever, ever, happen but if it does
7715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // we have to get a next random value.
7725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   while(TRUE)
7735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
7745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       GetRandomPrivate(dOut, curveData->p);
7755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // _cpri__EccPointMultiply does not return CRYPT_ECC_POINT if no point is
7765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // provided. CRYPT_PARAMTER should not be returned because the curve ID
7775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // has to be supported. Thus the only possible error is CRYPT_NO_RESULT.
7785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        retVal = _cpri__EccPointMultiply(Qout, curveId, dOut, NULL, NULL);
7795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(retVal != CRYPT_NO_RESULT)
7805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return retVal; // Will return CRYPT_SUCCESS
7815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
7825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
7835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECDSA      //%
7845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       SignEcdsa()
7875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function implements the ECDSA signing algorithm. The method is described in the comments below.
7895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      It is a fatal error if rOut, sOut, dIn, or digest are not provided.
7905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7915679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
7925679752bf24c21135884e987c4077e2f7184897Vadim BendeburySignEcdsa(
7935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *rOut,            //   OUT: r component of the signature
7945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *sOut,            //   OUT: s component of the signature
7955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                  curveId,         //   IN: the curve used in the signature
7965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                   //       process
7975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *dIn,             //   IN: the private key
7985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                         *digest           //   IN: the value to sign
7995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
8005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
8015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                        *bnK;
8025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                        *bnIk;
8035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                        *bnN;
8045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                        *bnR;
8055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
8065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                    *bnD;
8075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                    *bnZ;
8085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER        k;
8095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT             R;
8105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                    *context;
8115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CRYPT_RESULT               retVal = CRYPT_SUCCESS;
8125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    const ECC_CURVE_DATA      *curveData = GetCurveData(curveId);
8135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(rOut != NULL && sOut != NULL && dIn != NULL && digest != NULL);
8145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    context = BN_CTX_new();
8155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(context == NULL)
8165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
8175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX_start(context);
8185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnN = BN_CTX_get(context);
8195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnZ = BN_CTX_get(context);
8205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnR = BN_CTX_get(context);
8215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnD = BN_CTX_get(context);
8225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnIk = BN_CTX_get(context);
8235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    bnK = BN_CTX_get(context);
8245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Assume the size variables do not overflow, which should not happen in
8255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // the contexts that this function will be called.
8265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(curveData->n->size <= MAX_ECC_PARAMETER_BYTES);
8275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(   bnK == NULL
8285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
8295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_INTERNAL);
8305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   The algorithm as described in "Suite B Implementer's Guide to FIPS 186-3(ECDSA)"
8315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a per-message
8325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      secret number and its inverse modulo n. Since n is prime, the
8335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      output will be invalid only if there is a failure in the RBG.
8345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar
8355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      multiplication (see [Routines]), where G is the base point included in
8365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      the set of domain parameters.
8375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   3. Compute r = xR mod n. If r = 0, then return to Step 1. 1.
8385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   4. Use the selected hash function to compute H = Hash(M).
8395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   5. Convert the bit string H to an integer e as described in Appendix B.2.
8405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   6. Compute s = (k^-1 * (e + d * r)) mod n. If s = 0, return to Step 1.2.
8415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//   7. Return (r, s).
8425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Generate a random value k in the range 1 <= k < n
8435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Want a K value that is the same size as the curve order
8445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    k.t.size = curveData->n->size;
8455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    while(TRUE) // This implements the loop at step 6. If s is zero, start over.
8465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
8475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        while(TRUE)
8485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
8495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // Step 1 and 2 -- generate an ephemeral key and the modular inverse
8505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // of the private key.
8515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            while(TRUE)
8525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            {
8535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                GetRandomPrivate(&k, curveData->n);
8545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  // Do the point multiply to generate a point and check to see if
8555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  // the point it at infinity
8565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  if(    _cpri__EccPointMultiply(&R, curveId, &k, NULL, NULL)
8575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                      != CRYPT_NO_RESULT)
8585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                      break; // can only be CRYPT_SUCCESS
8595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              }
8605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // x coordinate is mod p. Make it mod n
8615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Assume the size variables do not overflow, which should not happen
8625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // in the contexts that this function will be called.
8635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              assert2Bsize(R.x.t);
8645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              BN_bin2bn(R.x.t.buffer, R.x.t.size, bnR);
8655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              BN_mod(bnR, bnR, bnN, context);
8665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Make sure that it is not zero;
8675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(BN_is_zero(bnR))
8685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  continue;
8695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Make sure that a modular inverse exists
8705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Assume the size variables do not overflow, which should not happen
8715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // in the contexts that this function will be called.
8725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              assert2Bsize(k.t);
8735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              BN_bin2bn(k.t.buffer, k.t.size, bnK);
8745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if( BN_mod_inverse(bnIk, bnK, bnN, context) != NULL)
8755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  break;
8765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
8775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Set z = leftmost bits of the digest
8785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // NOTE: This is implemented such that the key size needs to be
8795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        //        an even number of bytes in length.
8805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(digest->size > curveData->n->size)
8815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
8825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // Assume the size variables do not overflow, which should not happen
8835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // in the contexts that this function will be called.
8845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             pAssert(curveData->n->size <= MAX_ECC_KEY_BYTES);
8855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // digest is larger than n so truncate
8865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             BN_bin2bn(digest->buffer, curveData->n->size, bnZ);
8875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
8885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        else
8895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
8905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // Assume the size variables do not overflow, which should not happen
8915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // in the contexts that this function will be called.
8925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             pAssert(digest->size <= MAX_DIGEST_SIZE);
8935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // digest is same or smaller than n so use it all
8945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             BN_bin2bn(digest->buffer, digest->size, bnZ);
8955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
8965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Assume the size variables do not overflow, which should not happen in
8975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // the contexts that this function will be called.
8985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        assert2Bsize(dIn->t);
8995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(   bnZ == NULL
9005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // need the private scalar of the signing key
9015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL)
9025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              FAIL(FATAL_ERROR_INTERNAL);
9035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        //   NOTE: When the result of an operation is going to be reduced mod x
9045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        //   any modular multiplication is done so that the intermediate values
9055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        //   don't get too large.
9065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        //
9075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // now have inverse of K (bnIk), z (bnZ), r (bnR),      d (bnD) and n (bnN)
9085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Compute s = k^-1 (z + r*d)(mod n)
9095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            // first do d = r*d mod n
9105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if( !BN_mod_mul(bnD, bnR, bnD, bnN, context)
9115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // d = z + r * d
9125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             || !BN_add(bnD, bnZ, bnD)
9135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // d = k^(-1)(z + r * d)(mod n)
9145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             || !BN_mod_mul(bnD, bnIk, bnD, bnN, context)
9155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // convert to TPM2B format
9165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             || !BnTo2B(&sOut->b, bnD, curveData->n->size)
9175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             //   and write the modular reduced version of r
9185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             //   NOTE: this was deferred to reduce the number of
9195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             //   error checks.
9205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             ||   !BnTo2B(&rOut->b, bnR, curveData->n->size))
9215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              FAIL(FATAL_ERROR_INTERNAL);
9225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(!BN_is_zero(bnD))
9235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            break; // signature not zero so done
9245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // if the signature value was zero, start over
9255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
9265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Free up allocated BN values
9275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
9285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
9295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
9305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
9315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //%
9325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#if defined TPM_ALG_ECDAA || defined TPM_ALG_ECSCHNORR                //%
9335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       EcDaa()
9365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function is used to perform a modified Schnorr signature for ECDAA.
9385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function performs s = k + T * d mod n where
9395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) 'k is a random, or pseudo-random value used in the commit phase
9405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) T is the digest to be signed, and
9415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) d is a private key.
9425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      If tIn is NULL then use tOut as T
9435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                        Meaning
9455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SUCCESS                       signature created
9475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9485679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
9495679752bf24c21135884e987c4077e2f7184897Vadim BendeburyEcDaa(
9505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER              *tOut,             //   OUT: T component of the signature
9515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER              *sOut,             //   OUT: s component of the signature
9525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                     curveId,          //   IN: the curve used in signing
9535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER              *dIn,              //   IN: the private key
9545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                            *tIn,              //   IN: the value to sign
9555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER              *kIn               //   IN: a random value from commit
9565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
9575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
9585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                           *bnN, *bnK, *bnT, *bnD;
9595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                           *context;
9605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const TPM2B                      *n;
9615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA             *curveData = GetCurveData(curveId);
9625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                              OK = TRUE;
9635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Parameter checks
9645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(   sOut != NULL && dIn != NULL && tOut != NULL
9655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            && kIn != NULL && curveData != NULL);
9665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // this just saves key strokes
9675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   n = curveData->n;
9685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(tIn != NULL)
9695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Copy2B(&tOut->b, tIn);
9705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The size of dIn and kIn input scalars is limited by the size of the size
9715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // of a TPM2B_ECC_PARAMETER and tIn can be no larger than a digest.
9725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Make sure they are within range.
9735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(   (int) dIn->t.size <= MAX_ECC_KEY_BYTES
9745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           && (int) kIn->t.size <= MAX_ECC_KEY_BYTES
9755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && (int) tOut->t.size <= MAX_DIGEST_SIZE
9775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            );
9785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
9795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL)
9805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
9815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
9825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
9835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnK = BN_CTX_get(context);
9845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnT = BN_CTX_get(context);
9855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnD = BN_CTX_get(context);
9865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Check for allocation problems
9875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(bnD == NULL)
9885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
9895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Convert values
9905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   BN_bin2bn(n->buffer, n->size, bnN) == NULL
9915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(kIn->t.buffer, kIn->t.size, bnK) == NULL
9925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(dIn->t.buffer, dIn->t.size, bnD) == NULL
9935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || BN_bin2bn(tOut->t.buffer, tOut->t.size, bnT) == NULL)
9945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
9955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute T = T mod n
9965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OK = OK && BN_mod(bnT, bnT, bnN, context);
9975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // compute (s = k + T * d mod n)
9985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           //   d = T * d mod n
9995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OK = OK && BN_mod_mul(bnD, bnT, bnD, bnN, context) == 1;
10005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           //   d = k + T * d mod n
10015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OK = OK && BN_mod_add(bnD, bnK, bnD, bnN, context) == 1;
10025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           //   s = d
10035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OK = OK && BnTo2B(&sOut->b, bnD, n->size);
10045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           //   r = T
10055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OK = OK && BnTo2B(&tOut->b, bnT, n->size);
10065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!OK)
10075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
10085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Cleanup
10095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
10105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
10115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return CRYPT_SUCCESS;
10125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
10135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //%
10145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECSCHNORR //%
10155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10170343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//       Mod2B()
10180343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//
10190343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//      Function does modular reduction of TPM2B values.
10200343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//
10210343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendeburystatic CRYPT_RESULT
10220343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim BendeburyMod2B(
10230343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    TPM2B                *x,                 // IN/OUT: value to reduce
10240343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    const TPM2B          *n                  // IN: mod
10250343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    )
10260343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury{
10270343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    int         compare;
10280343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    compare = _math__uComp(x->size, x->buffer, n->size, n->buffer);
10290343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    if(compare < 0)
10300343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        // if x < n, then mod is x
10310343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        return CRYPT_SUCCESS;
10320343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    if(compare == 0)
10330343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    {
10340343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        // if x == n then mod is 0
10350343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        x->size = 0;
10360343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        x->buffer[0] = 0;
10370343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury        return CRYPT_SUCCESS;
10380343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury    }
10390343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury   return _math__Div(x, n, NULL, x);
10400343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury}
10410343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury
10420343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//
10430343d5bfce6fbea1cad2d626e14382f6ebe28667Vadim Bendebury//
10445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       SchnorrEcc()
10455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function is used to perform a modified Schnorr signature.
10475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function will generate a random value k and compute
10485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) (xR, yR) = [k]G
10495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) r = hash(P || xR)(mod n)
10505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) s= k + r * ds
10515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      d) return the tuple T, s
10525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                  Meaning
10575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SUCCESS                 signature created
10595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      CRYPT_SCHEME                  hashAlg can't produce zero-length digest
10605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10615679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
10625679752bf24c21135884e987c4077e2f7184897Vadim BendeburySchnorrEcc(
10635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *rOut,               //   OUT: r component of the signature
10645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *sOut,               //   OUT: s component of the signature
10655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                  hashAlg,            //   IN: hash algorithm used
10665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE               curveId,            //   IN: the curve used in signing
10675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *dIn,                //   IN: the private key
10685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                      *digest,             //   IN: the digest to sign
10695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *kIn                 //   IN: for testing
10705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
10715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
10725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER      k;
10735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                  *bnR, *bnN, *bnK, *bnT, *bnD;
10745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                  *context;
10755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const TPM2B             *n;
10765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                *pR = NULL;
10775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                *group = NULL;
10785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CPRI_HASH_STATE          hashState;
10795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                   digestSize = _cpri__GetDigestSize(hashAlg);
10805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA    *curveData = GetCurveData(curveId);
10815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_PARAMETER_BYTES));
10825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_T                  T2b;
10835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                     OK = TRUE;
10845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Parameter checks
10855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Must have a place for the 'r' and 's' parts of the signature, a private
10865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // key ('d')
10875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(   rOut != NULL && sOut != NULL && dIn != NULL
10885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           && digest != NULL && curveData != NULL);
10895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // to save key strokes
10905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   n = curveData->n;
10915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If the digest does not produce a hash, then null the signature and return
10925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // a failure.
10935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(digestSize == 0)
10945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
10955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       rOut->t.size = 0;
10965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       sOut->t.size = 0;
10975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_SCHEME;
10985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
10995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Allocate big number values
11005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
11015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL)
11025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
11035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
11045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnR = BN_CTX_get(context);
11055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
11065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnK = BN_CTX_get(context);
11075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnT = BN_CTX_get(context);
11085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnD = BN_CTX_get(context);
11095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   bnD == NULL
11105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           // initialize the group parameters
11115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || (group = EccCurveInit(curveId, context)) == NULL
11125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // allocate a local point
11135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || (pR = EC_POINT_new(group)) == NULL
11145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury     )
11155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_ALLOCATION);
11165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
11175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
11185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   while(OK)
11195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
11205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// a) set k to a random value such that 1 k n-1
11215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(kIn != NULL)
11225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
11235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            Copy2B(&k.b, &kIn->b); // copy input k if testing
11245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            OK = FALSE;              // not OK to loop
11255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       }
11265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       else
11275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // If get a random value in the correct range
11285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            GetRandomPrivate(&k, n);
11295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Convert 'k' and generate pR = ['k']G
11305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BnFrom2B(bnK, &k.b);
11315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// b) compute E (xE, yE) [k]G
11325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(PointMul(group, pR, bnK, NULL, NULL, context) == CRYPT_NO_RESULT)
11335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// c) if E is the point at infinity, go to a)
11345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           continue;
11355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// d) compute e xE (mod n)
11365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Get the x coordinate of the point
11375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       EC_POINT_get_affine_coordinates_GFp(group, pR, bnR, NULL, context);
11385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // make (mod n)
11395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BN_mod(bnR, bnR, bnN, context);
11405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// e) if e is zero, go to a)
11415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(BN_is_zero(bnR))
11425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           continue;
11435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Convert xR to a string (use T as a temp)
11445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BnTo2B(&T2b.b, bnR, (UINT16)(BN_num_bits(bnR)+7)/8);
11455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// f) compute r HschemeHash(P || e) (mod n)
11465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       _cpri__StartHash(hashAlg, FALSE, &hashState);
11475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       _cpri__UpdateHash(&hashState, digest->size, digest->buffer);
11485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       _cpri__UpdateHash(&hashState, T2b.t.size, T2b.t.buffer);
11495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(_cpri__CompleteHash(&hashState, digestSize, T2b.b.buffer) != digestSize)
11505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
11515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       T2b.t.size = digestSize;
11525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BnFrom2B(bnT, &T2b.b);
11535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BN_div(NULL, bnT, bnT, bnN, context);
11545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BnTo2B(&rOut->b, bnT, (UINT16)BN_num_bytes(bnT));
11555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // We have a value and we are going to exit the loop successfully
11565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        OK = TRUE;
11575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        break;
11585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
11595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Cleanup
11605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT_free(pR);
11615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP_free(group);
11625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
11635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
11645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If we have a value, finish the signature
11655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(OK)
11665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return EcDaa(rOut, sOut, curveId, dIn, NULL, &k);
11675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
11685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_NO_RESULT;
11695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
11705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //%
11715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2 //%
11725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG //%
11735679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic int
11745679752bf24c21135884e987c4077e2f7184897Vadim Bendeburycmp_bn2hex(
11755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM              *bn,               // IN: big number value
11765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const char          *c                 // IN: character string number
11775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
11785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
11795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int         result;
11805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM      *bnC = BN_new();
11815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(bnC != NULL);
11825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_hex2bn(&bnC, c);
11835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = BN_ucmp(bn, bnC);
11845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_free(bnC);
11855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return result;
11865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
11875679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic int
11885679752bf24c21135884e987c4077e2f7184897Vadim Bendeburycmp_2B2hex(
11895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B               *a,                // IN: TPM2B number to compare
11905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const char          *c                 // IN: character string
11915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
11925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
11935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int            result;
11945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int            sl = strlen(c);
11955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM         *bnA;
11965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = (a->size * 2) - sl;
11975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result != 0)
11985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return result;
11995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert((bnA = BN_bin2bn(a->buffer, a->size, NULL)) != NULL);
12005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = cmp_bn2hex(bnA, c);
12015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_free(bnA);
12025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return result;
12035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
12045679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
12055679752bf24c21135884e987c4077e2f7184897Vadim Bendeburycpy_hexTo2B(
12065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B               *b,                // OUT: receives value
12075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const char          *c                 // IN: source string
12085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
12095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
12105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM      *bnB = BN_new();
12115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert((strlen(c) & 1) == 0);         // must have an even number of digits
12125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   b->size = strlen(c) / 2;
12135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_hex2bn(&bnB, c);
12145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(bnB != NULL);
12155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnTo2B(b, bnB, b->size);
12165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_free(bnB);
12175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
12185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //% _SM2_SIGN_DEBUG
12195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        SignSM2()
12225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function signs a digest using the method defined in SM2 Part 2. The method in the standard will add
12245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       a header to the message to be signed that is a hash of the values that define the key. This then hashed
12255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       with the message to produce a digest (e) that is signed. This function signs e.
12265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
12315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                     sign worked
12335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12345679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
12355679752bf24c21135884e987c4077e2f7184897Vadim BendeburySignSM2(
12365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *rOut,                 //   OUT: r component of the signature
12375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *sOut,                 //   OUT: s component of the signature
12385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                   curveId,              //   IN: the curve used in signing
12395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *dIn,                  //   IN: the private key
12405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                          *digest                //   IN: the digest to sign
12415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
12425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
12435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnR;
12445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnS;
12455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnN;
12465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnK;
12475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnX1;
12485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnD;
12495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnT;        // temp
12505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnE;
12515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                  *context;
12525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER      k;
12535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT           p2Br;
12545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA    *curveData = GetCurveData(curveId);
12555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(curveData != NULL);
12565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
12575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
12585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnK = BN_CTX_get(context);
12595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnR = BN_CTX_get(context);
12605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnS = BN_CTX_get(context);
12615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnX1 = BN_CTX_get(context);
12625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
12635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnD = BN_CTX_get(context);
12645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnT = BN_CTX_get(context);
12655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnE = BN_CTX_get(context);
12665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(bnE == NULL)
12675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
12685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnE, digest);
12695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnN, curveData->n);
12705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnD, &dIn->b);
12715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
12725679752bf24c21135884e987c4077e2f7184897Vadim BendeburyBN_hex2bn(&bnE, "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76");
12735679752bf24c21135884e987c4077e2f7184897Vadim BendeburyBN_hex2bn(&bnD, "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263");
12745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
12755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// A3: Use random number generator to generate random number 1 <= k <= n-1;
12765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// NOTE: Ax: numbers are from the SM2 standard
12775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   k.t.size = curveData->n->size;
12785679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyloop:
12795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
12805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Get a random number
12815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       _cpri__GenerateRandom(k.t.size, k.t.buffer);
12825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
12835679752bf24c21135884e987c4077e2f7184897Vadim BendeburyBN_hex2bn(&bnK, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F");
12845679752bf24c21135884e987c4077e2f7184897Vadim BendeburyBnTo2B(&k.b,bnK, 32);
12855679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyk.t.size = 32;
12865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
12875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       //make sure that the number is 0 < k < n
12885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BnFrom2B(bnK, &k.b);
12895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(      BN_ucmp(bnK, bnN) >= 0
12905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              || BN_is_zero(bnK))
12915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              goto loop;
12925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according
12935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// to details specified in 4.2.7 in Part 1 of this document, transform the
12945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// data type of x1 into an integer;
12955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(    _cpri__EccPointMultiply(&p2Br, curveId, &k, NULL, NULL)
12965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           == CRYPT_NO_RESULT)
12975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto loop;
12985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        BnFrom2B(bnX1, &p2Br.x.b);
12995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// A5: Figure out r = (e + x1) mod n,
13005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(!BN_mod_add(bnR, bnE, bnX1, bnN, context))
13015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
13025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
13035679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_bn2hex(bnR,
13045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1")
13055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       == 0);
13065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           // if r=0 or r+k=n, return to A3;
13085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(!BN_add(bnT, bnK, bnR))
13095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
13105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(BN_is_zero(bnR) || BN_ucmp(bnT, bnN) == 0)
13115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto loop;
13125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, if s=0, return to A3;
13135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // compute t = (1+d)-1
13145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BN_copy(bnT, bnD);
13155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(     !BN_add_word(bnT, 1)
13165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || !BN_mod_inverse(bnT, bnT, bnN, context) // (1 + dA)^-1 mod n
13175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           )
13185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             FAIL(FATAL_ERROR_INTERNAL);
13195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
13205679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_bn2hex(bnT,
13215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 "79BFCF3052C80DA7B939E0C6914A18CBB2D96D8555256E83122743A7D4F5F956")
13225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       == 0);
13235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // compute s = t * (k - r * dA) mod n
13255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(     !BN_mod_mul(bnS, bnD, bnR, bnN, context) // (r * dA) mod n
13265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || !BN_mod_sub(bnS, bnK, bnS, bnN, context) // (k - (r * dA) mod n
13275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || !BN_mod_mul(bnS, bnT, bnS, bnN, context))// t * (k - (r * dA) mod n
13285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
13295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
13305679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_bn2hex(bnS,
13315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7")
13325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       == 0);
13335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(BN_is_zero(bnS))
13355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            goto loop;
13365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
13375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// A7: According to details specified in 4.2.1 in Part 1 of this document, transform
13385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// the data type of r, s into bit strings, signature of message M is (r, s).
13395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnTo2B(&rOut->b, bnR, curveData->n->size);
13405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnTo2B(&sOut->b, bnS, curveData->n->size);
13415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
13425679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_2B2hex(&rOut->b,
13435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1")
13445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       == 0);
13455679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_2B2hex(&sOut->b,
13465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7")
13475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        == 0);
13485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
13505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
13515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return CRYPT_SUCCESS;
13525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
13535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //% TPM_ALG_SM2
13545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        _cpri__SignEcc()
13575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function is the dispatch function for the various ECC-based signing schemes.
13595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
13615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SCHEME                      scheme is not supported
13635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
13645679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
13655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__SignEcc(
13665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *rOut,              //   OUT: r component of the signature
13675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *sOut,              //   OUT: s component of the signature
13685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                      scheme,            //   IN: the scheme selector
13695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                      hashAlg,           //   IN: the hash algorithm if need
13705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                   curveId,           //   IN: the curve used in the signature
13715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                      //       process
13725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *dIn,               //   IN: the private key
13735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                          *digest,            //   IN: the digest to sign
13745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *kIn                //   IN: k for input
13755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
13765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
13775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   switch (scheme)
13785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
13795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECDSA:
13805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           // SignEcdsa always works
13815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return SignEcdsa(rOut, sOut, curveId, dIn, digest);
13825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
13835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECDAA
13845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECDAA:
13855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           if(rOut != NULL)
13865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                rOut->b.size = 0;
13875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return EcDaa(rOut, sOut, curveId, dIn, digest, kIn);
13885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
13895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECSCHNORR
13915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECSCHNORR:
13925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return SchnorrEcc(rOut, sOut, hashAlg, curveId, dIn, digest, kIn);
13935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
13945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
13955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2
13965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_SM2:
13975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return SignSM2(rOut, sOut, curveId, dIn, digest);
13985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
13995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
14005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       default:
14015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return CRYPT_SCHEME;
14025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
14035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
14045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECDSA //%
14055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        ValidateSignatureEcdsa()
14085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function validates an ECDSA signature. rIn and sIn shoudl have been checked to make sure that
14105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       they are not zero.
14115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                  Meaning
14135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                 signature valid
14155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_FAIL                    signature not valid
14165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
14175679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
14185679752bf24c21135884e987c4077e2f7184897Vadim BendeburyValidateSignatureEcdsa(
14195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *rIn,                //   IN: r component of the signature
14205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        *sIn,                //   IN: s component of the signature
14215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE               curveId,            //   IN: the curve used in the signature
14225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                   //       process
14235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT             *Qin,                //   IN: the public point of the key
14245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                      *digest              //   IN: the digest that was signed
14255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
14265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
14275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         U1;
14285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         U2;
14295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              R;
14305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const TPM2B                *n;
14315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                     *context;
14325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                   *pQ = NULL;
14335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                   *group = NULL;
14345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnU1;
14355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnU2;
14365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnR;
14375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnS;
14385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnW;
14395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnV;
14405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnN;
14415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnE;
14425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnQx;
14435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                     *bnQy;
14445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CRYPT_RESULT                retVal = CRYPT_FAIL;
14455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int                         t;
14465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA       *curveData = GetCurveData(curveId);
14475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The curve selector should have been filtered by the unmarshaling process
14485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert (curveData != NULL);
14495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   n = curveData->n;
14505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 1. If r and s are not both integers in the interval [1, n - 1], output
14515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//    INVALID.
14525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// rIn and sIn are known to be greater than zero (was checked by the caller).
14535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(     _math__uComp(rIn->t.size, rIn->t.buffer, n->size, n->buffer) >= 0
14545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || _math__uComp(sIn->t.size, sIn->t.buffer, n->size, n->buffer) >= 0
14555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury     )
14565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      return CRYPT_FAIL;
14575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
14585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL)
14595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
14605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
14615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnR = BN_CTX_get(context);
14625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnS = BN_CTX_get(context);
14635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
14645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnE = BN_CTX_get(context);
14655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnV = BN_CTX_get(context);
14665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnW = BN_CTX_get(context);
14675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnQx = BN_CTX_get(context);
14685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnQy = BN_CTX_get(context);
14695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnU1 = BN_CTX_get(context);
14705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnU2 = BN_CTX_get(context);
14715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Assume the size variables do not overflow, which should not happen in
14725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // the contexts that this function will be called.
14735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   assert2Bsize(Qin->x.t);
14745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   assert2Bsize(rIn->t);
14755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   assert2Bsize(sIn->t);
14765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // BN_CTX_get() is sticky so only need to check the last value to know that
14775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // all worked.
14785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   bnU2 == NULL
14795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // initialize the group parameters
14805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || (group = EccCurveInit(curveId, context)) == NULL
14815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // allocate a local point
14825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || (pQ = EC_POINT_new(group)) == NULL
14835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       //   use the public key values (QxIn and QyIn) to initialize Q
14845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       ||   BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQx) == NULL
14855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       ||   BN_bin2bn(Qin->x.t.buffer, Qin->x.t.size, bnQy) == NULL
14865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       ||   !EC_POINT_set_affine_coordinates_GFp(group, pQ, bnQx, bnQy, context)
14875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // convert the signature values
14885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || BN_bin2bn(rIn->t.buffer, rIn->t.size, bnR) == NULL
14895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || BN_bin2bn(sIn->t.buffer, sIn->t.size, bnS) == NULL
14905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // convert the curve order
14915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || BN_bin2bn(curveData->n->buffer, curveData->n->size, bnN) == NULL)
14925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_INTERNAL);
14935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 2. Use the selected hash function to compute H0 = Hash(M0).
14945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // This is an input parameter
14955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 3. Convert the bit string H0 to an integer e as described in Appendix B.2.
14965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   t = (digest->size > rIn->t.size) ? rIn->t.size : digest->size;
14975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(BN_bin2bn(digest->buffer, t, bnE) == NULL)
14985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
14995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1.
15005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if (BN_mod_inverse(bnW, bnS, bnN, context) == NULL)
15015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
15025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 5. Compute u1 = (e' *   w) mod n, and compute u2 = (r' *     w) mod n.
15035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   !BN_mod_mul(bnU1, bnE, bnW, bnN, context)
15045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || !BN_mod_mul(bnU2, bnR, bnW, bnN, context))
15055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
15065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnTo2B(&U1.b, bnU1, (INT16) BN_num_bytes(bnU1));
15075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnTo2B(&U2.b, bnU2, (INT16) BN_num_bytes(bnU2));
15085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC
15095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//    scalar multiplication and EC addition (see [Routines]). If R is equal to
15105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//    the point at infinity O, output INVALID.
15115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(_cpri__EccPointMultiply(&R, curveId, &U1, Qin, &U2) == CRYPT_SUCCESS)
15125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
15135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // 7. Compute v = Rx mod n.
15145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(    BN_bin2bn(R.x.t.buffer, R.x.t.size, bnV) == NULL
15155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || !BN_mod(bnV, bnV, bnN, context))
15165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
15175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID
15185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(BN_cmp(bnV, bnR) == 0)
15195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           retVal = CRYPT_SUCCESS;
15205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
15215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQ != NULL) EC_POINT_free(pQ);
15225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(group != NULL) EC_GROUP_free(group);
15235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
15245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
15255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
15265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
15275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif      //% TPM_ALG_ECDSA
15285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECSCHNORR //%
15295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        ValidateSignatureEcSchnorr()
15325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function is used to validate an EC Schnorr signature. rIn and sIn are required to be greater than
15345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       zero. This is checked in _cpri__ValidateSignatureEcc().
15355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                   Meaning
15375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                  signature valid
15395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_FAIL                     signature not valid
15405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SCHEME                   hashAlg is not supported
15415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
15425679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
15435679752bf24c21135884e987c4077e2f7184897Vadim BendeburyValidateSignatureEcSchnorr(
15445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         *rIn,                //   IN: r component of the signature
15455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         *sIn,                //   IN: s component of the signature
15465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                   hashAlg,            //   IN: hash algorithm of the signature
15475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                curveId,            //   IN: the curve used in the signature
15485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                    //       process
15495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              *Qin,                //   IN: the public point of the key
15505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                       *digest              //   IN: the digest that was signed
15515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
15525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
15535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT               pE;
15545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const TPM2B                 *n;
15555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CPRI_HASH_STATE              hashState;
15565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST                 rPrime;
15575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER          minusR;
15585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                       digestSize = _cpri__GetDigestSize(hashAlg);
15595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA        *curveData = GetCurveData(curveId);
15605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The curve parameter should have been filtered by unmarshaling code
15615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(curveData != NULL);
15625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(digestSize == 0)
15635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_SCHEME;
15645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Input parameter validation
15655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(rIn != NULL && sIn != NULL && Qin != NULL && digest != NULL);
15665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   n = curveData->n;
15675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // if sIn or rIn are not between 1 and N-1, signature check fails
15685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // sIn and rIn were verified to be non-zero by the caller
15695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(   _math__uComp(sIn->b.size, sIn->b.buffer, n->size, n->buffer) >= 0
15705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || _math__uComp(rIn->b.size, rIn->b.buffer, n->size, n->buffer) >= 0
15715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury     )
15725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_FAIL;
15735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   //E = [s]InG - [r]InQ
15745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   _math__sub(n->size, n->buffer,
15755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              rIn->t.size, rIn->t.buffer,
15765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              &minusR.t.size, minusR.t.buffer);
15775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(_cpri__EccPointMultiply(&pE, curveId, sIn, Qin, &minusR) != CRYPT_SUCCESS)
15785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_FAIL;
15795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Ex = Ex mod N
15805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(Mod2B(&pE.x.b, n) != CRYPT_SUCCESS)
15815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
15825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   _math__Normalize2B(&pE.x.b);
15835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // rPrime = h(digest || pE.x) mod n;
15845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   _cpri__StartHash(hashAlg, FALSE, &hashState);
15855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   _cpri__UpdateHash(&hashState, digest->size, digest->buffer);
15865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   _cpri__UpdateHash(&hashState, pE.x.t.size, pE.x.t.buffer);
15875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(_cpri__CompleteHash(&hashState, digestSize, rPrime.t.buffer) != digestSize)
15885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
15895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   rPrime.t.size = digestSize;
15905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // rPrime = rPrime (mod n)
15915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(Mod2B(&rPrime.b, n) != CRYPT_SUCCESS)
15925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
15935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // if the values don't match, then the signature is bad
15945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(_math__uComp(rIn->t.size, rIn->t.buffer,
15955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   rPrime.t.size, rPrime.t.buffer) != 0)
15965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_FAIL;
15975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
15985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return CRYPT_SUCCESS;
15995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
16005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //% TPM_ALG_ECSCHNORR
16015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2 //%
16025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        ValidateSignatueSM2Dsa()
16055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function is used to validate an SM2 signature.
16075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
16095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                     signature valid
16115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_FAIL                        signature not valid
16125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16135679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
16145679752bf24c21135884e987c4077e2f7184897Vadim BendeburyValidateSignatureSM2Dsa(
16155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *rIn,                //   IN: r component of the signature
16165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER            *sIn,                //   IN: s component of the signature
16175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                   curveId,            //   IN: the curve used in the signature
16185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       process
16195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                 *Qin,                //   IN: the public point of the key
16205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                          *digest              //   IN: the digest that was signed
16215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
16225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
16235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnR;
16245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnRp;
16255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnT;
16265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnS;
16275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                         *bnE;
1628ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   BIGNUM                         *order;
16295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                       *pQ;
16305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                         *context;
16315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                       *group = NULL;
16325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA           *curveData = GetCurveData(curveId);
16335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                            fail = FALSE;
16345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
16355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((context = BN_CTX_new()) == NULL || curveData == NULL)
16365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
16375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnR = BN_CTX_get(context);
16385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnRp= BN_CTX_get(context);
16395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnE = BN_CTX_get(context);
16405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnT = BN_CTX_get(context);
16415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnS = BN_CTX_get(context);
1642ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   order = BN_CTX_get(context);
1643ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   if(   order == NULL
16445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      || (group = EccCurveInit(curveId, context)) == NULL)
16455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
16465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
16475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   cpy_hexTo2B(&Qin->x.b,
16485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A");
16495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   cpy_hexTo2B(&Qin->y.b,
16505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857");
16515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   cpy_hexTo2B(digest,
16525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          "B524F552CD82B8B028476E005C377FB19A87E6FC682D48BB5D42E3D9B9EFFE76");
16535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
16545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQ = EccInitPoint2B(group, Qin, context);
16555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
16565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, bnS, context));
16575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(cmp_bn2hex(bnT,
16585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A")
16595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           == 0);
16605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(cmp_bn2hex(bnS,
16615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857")
16625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           == 0);
16635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
16645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnR, &rIn->b);
16655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnS, &sIn->b);
16665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnE, digest);
16675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
16685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Make sure that the input signature is the test signature
16695679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_2B2hex(&rIn->b,
16705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1") == 0);
16715679752bf24c21135884e987c4077e2f7184897Vadim BendeburypAssert(cmp_2B2hex(&sIn->b,
16725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7") == 0);
16735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
16745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// a) verify that r and s are in the inclusive interval 1 to (n   1)
1675ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   if (!EC_GROUP_get_order(group, order, context)) goto Cleanup;
1676ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   fail = (BN_ucmp(bnR, order) >= 0);
1677ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   fail = (BN_ucmp(bnS, order) >= 0) || fail;
16785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(fail)
16795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // There is no reason to continue. Since r and s are inputs from the caller,
16805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // they can know that the values are not in the proper range. So, exiting here
16815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // does not disclose any information.
16825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       goto Cleanup;
16835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// b) compute t := (r + s) mod n
1684ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   if(!BN_mod_add(bnT, bnR, bnS, order, context))
16855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
16865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
16875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(cmp_bn2hex(bnT,
16885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "2B75F07ED7ECE7CCC1C8986B991F441AD324D6D619FE06DD63ED32E0C997C801")
16895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           == 0);
16905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
16915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// c) verify that t > 0
16925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(BN_is_zero(bnT)) {
16935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       fail = TRUE;
16945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // set to a value that should allow rest of the computations to run without
16955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // trouble
16965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         BN_copy(bnT, bnS);
16975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
16985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// d) compute (x, y) := [s]G + [t]Q
16995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!EC_POINT_mul(group, pQ, bnS, pQ, bnT, context))
17005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
17015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get the x coordinate of the point
17025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!EC_POINT_get_affine_coordinates_GFp(group, pQ, bnT, NULL, context))
17035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
17045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef _SM2_SIGN_DEBUG
17055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(cmp_bn2hex(bnT,
17065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               "110FCDA57615705D5E7B9324AC4B856D23E6D9188B2AE47759514657CE25D112")
17075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury               == 0);
17085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
17095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// e) compute r' := (e + x) mod n (the x coordinate is in bnT)
1710ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   if(!BN_mod_add(bnRp, bnE, bnT, order, context))
17115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
17125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// f) verify that r' = r
17135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   fail = BN_ucmp(bnR, bnRp) != 0 || fail;
17145679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup:
17155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQ) EC_POINT_free(pQ);
17165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(group) EC_GROUP_free(group);
17175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
17185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
17195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(fail)
17205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return CRYPT_FAIL;
17215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
17225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return CRYPT_SUCCESS;
17235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
17245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //% TPM_ALG_SM2
17255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        _cpri__ValidateSignatureEcc()
17285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function validates
17305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
17325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                     signature is valid
17345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_FAIL                        not a valid signature
17355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SCHEME                      unsupported scheme
17365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17375679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
17385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__ValidateSignatureEcc(
17395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER           *rIn,                  //   IN: r component of the signature
17405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER           *sIn,                  //   IN: s component of the signature
17415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID                     scheme,               //   IN: the scheme selector
17425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID                     hashAlg,              //   IN: the hash algorithm used (not used
17435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                         //       in all schemes)
17445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE                   curveId,             //   IN: the curve used in the signature
17455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                         //       process
17465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                *Qin,                  //   IN: the public point of the key
17475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B                         *digest                //   IN: the digest that was signed
17485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
17495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
17505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CRYPT_RESULT                  retVal;
17515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // return failure if either part of the signature is zero
17525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(_math__Normalize2B(&rIn->b) == 0 || _math__Normalize2B(&sIn->b) == 0)
17535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return CRYPT_FAIL;
17545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   switch (scheme)
17555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
17565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECDSA:
17575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           retVal = ValidateSignatureEcdsa(rIn, sIn, curveId, Qin, digest);
17585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
17595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef   TPM_ALG_ECSCHNORR
17605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        case TPM_ALG_ECSCHNORR:
17615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            retVal = ValidateSignatureEcSchnorr(rIn, sIn, hashAlg, curveId, Qin,
17625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                              digest);
17635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            break;
17645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
17655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2
17665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_SM2:
17675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           retVal = ValidateSignatureSM2Dsa(rIn, sIn, curveId, Qin, digest);
17685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
17695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       default:
17705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           retVal = CRYPT_SCHEME;
17715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
17725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
17735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
17745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
17755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#if CC_ZGen_2Phase == YES //%
17765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECMQV
17775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        avf1()
17805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function does the associated value computation required by MQV key exchange. Process:
17825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       a) Convert xQ to an integer xqi using the convention specified in Appendix C.3.
17835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)).
17845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2)
17855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
17865679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic BOOL
17875679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyavf1(
17885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM              *bnX,               // IN/OUT: the reduced value
17895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM              *bnN                // IN: the order of the curve
17905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
17915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
17925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// compute f = 2^(ceil(ceil(log2(n)) / 2))
17935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int                      f = (BN_num_bits(bnN) + 1) / 2;
17945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// x' = 2^f + (x mod 2^f)
17955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_mask_bits(bnX, f);   // This is mod 2*2^f but it doesn't matter because
17965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                           // the next operation will SET the extra bit anyway
17975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_set_bit(bnX, f);
17985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TRUE;
17995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
18005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        C_2_2_MQV()
18035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC MQV).
18055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CAUTION: Implementation of this function may require use of essential claims in patents not owned by
18065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TCG members.
18075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly
18085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       catastrophically, if this is not the case.
18095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
18135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                     results is valid
18155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_NO_RESULT                   the value for dsA does not give a valid point on the curve
18165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
18175679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
18185679752bf24c21135884e987c4077e2f7184897Vadim BendeburyC_2_2_MQV(
18195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                  *outZ,                //   OUT: the computed point
18205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                    curveId,             //   IN: the curve for the computations
18215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER             *dsA,                 //   IN: static private TPM key
18225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER             *deA,                 //   IN: ephemeral private TPM key
18235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                  *QsB,                 //   IN: static public party B key
18245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                  *QeB                  //   IN: ephemeral public party B key
18255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
18265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
18275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                          *context;
18285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                        *pQeA = NULL;
18295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                        *pQeB = NULL;
18305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                        *pQsB = NULL;
18315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                        *group = NULL;
18325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnTa;
18335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnDeA;
18345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnDsA;
18355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnXeA;         // x coordinate of ephemeral party A key
18365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnH;
18375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnN;
18385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                          *bnXeB;
18395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA            *curveData = GetCurveData(curveId);
18405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CRYPT_RESULT                    retVal;
18415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(       curveData != NULL && outZ != NULL && dsA != NULL
18425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           &&           deA != NULL && QsB != NULL && QeB != NULL);
18435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
18445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL || curveData == NULL)
18455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
18465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
18475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnTa = BN_CTX_get(context);
18485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnDeA = BN_CTX_get(context);
18495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnDsA = BN_CTX_get(context);
18505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnXeA = BN_CTX_get(context);
18515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnH = BN_CTX_get(context);
18525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
18535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnXeB = BN_CTX_get(context);
18545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(bnXeB == NULL)
18555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
18565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Process:
18575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
18585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
18595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 3. If P = O, output an error indicator.
18605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 4. Z=xP, where xP is the x-coordinate of P.
18615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initialize group parameters and local values of input
18625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((group = EccCurveInit(curveId, context)) == NULL)
18635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
18645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((pQeA = EC_POINT_new(group)) == NULL)
18655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
18665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnDeA, &deA->b);
18675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnDsA, &dsA->b);
18685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnH, curveData->h);
18695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnN, curveData->n);
18705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnXeB, &QeB->x.b);
18715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQeB = EccInitPoint2B(group, QeB, context);
18725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQsB = EccInitPoint2B(group, QsB, context);
18735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute the public ephemeral key pQeA = [de,A]G
18745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(    (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context))
18755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      != CRYPT_SUCCESS)
18765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       goto Cleanup;
18775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1)
18785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
18795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n.
18805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// tA := (ds,A + de,A avf(Xe,A)) mod n (3)
18815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n
18825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Ta = avf(XeA);
18835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_copy(bnTa, bnXeA);
18845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   avf1(bnTa, bnN);
18855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(// do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n
18865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         !BN_mod_mul(bnTa, bnDsA, bnTa, bnN, context)
18875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n
18885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || !BN_mod_add(bnTa, bnDeA, bnTa, bnN, context)
18895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
18905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
18915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B).
18925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Put this in because almost every case of h is == 1 so skip the call when
18935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // not necessary.
18945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!BN_is_one(bnH))
18955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
18965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Cofactor is not 1 so compute Ta := Ta * h mod n
18975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(!BN_mul(bnTa, bnTa, bnH, context))
18985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
18995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
19005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Now that 'tA' is (h * 'tA' mod n)
19015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B).
19025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // first, compute XeB = avf(XeB)
19035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   avf1(bnXeB, bnN);
19045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // QsB := [XeB]QsB
19055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(     !EC_POINT_mul(group, pQsB, NULL, pQsB, bnXeB, context)
19065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // QeB := QsB + QeB
19075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        || !EC_POINT_add(group, pQeB, pQeB, pQsB, context)
19085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       )
19095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        FAIL(FATAL_ERROR_INTERNAL);
19105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
19115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS)
19125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert BIGNUM E to TPM2B E
19135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context);
19145679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup:
19155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQeA != NULL) EC_POINT_free(pQeA);
19165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQeB != NULL) EC_POINT_free(pQeB);
19175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQsB != NULL) EC_POINT_free(pQsB);
19185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(group != NULL) EC_GROUP_free(group);
19195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
19205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
19215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
19225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
19235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif // TPM_ALG_ECMQV
19245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2 //%
19255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        avfSm2()
19285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function does the associated value computation required by SM2 key exchange. This is different
19305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       form the avf() in the international standards because it returns a value that is half the size of the value
19315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       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
19325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       means that an input value of 14 (1110b) would return a value of 110b with the standard but 10b with the
19335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       scheme in SM2.
19345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19355679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic BOOL
19365679752bf24c21135884e987c4077e2f7184897Vadim BendeburyavfSm2(
19375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM              *bnX,                  // IN/OUT: the reduced value
19385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM              *bnN                   // IN: the order of the curve
19395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
19405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
19415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// a) set w := ceil(ceil(log2(n)) / 2) - 1
19425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   int                      w = ((BN_num_bits(bnN) + 1) / 2) - 1;
19435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// b) set x' := 2^w + ( x & (2^w - 1))
19445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// This is just like the avf for MQV where x' = 2^w + (x mod 2^w)
19455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_mask_bits(bnX, w);   // as wiht avf1, this is too big by a factor of 2 but
19465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                           // it doesn't matter becasue we SET the extra bit anyway
19475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_set_bit(bnX, w);
19485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TRUE;
19495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
19505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to compute
19525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA +
19535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral private
19545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       key. All points are required to be on the curve of inQsA. The function will fail catastrophically if this is not
19555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       the case
19565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                      Meaning
19585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SUCCESS                     results is valid
19605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_NO_RESULT                   the value for dsA does not give a valid point on the curve
19615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19625679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
19635679752bf24c21135884e987c4077e2f7184897Vadim BendeburySM2KeyExchange(
19645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                 *outZ,                //   OUT: the computed point
19655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ECC_CURVE                   curveId,             //   IN: the curve for the computations
19665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER            *dsA,                 //   IN: static private TPM key
19675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_ECC_PARAMETER            *deA,                 //   IN: ephemeral private TPM key
19685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                 *QsB,                 //   IN: static public party B key
19695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMS_ECC_POINT                 *QeB                  //   IN: ephemeral public party B key
19705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
19715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
19725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BN_CTX                         *context;
19735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT                       *pQeA = NULL;
19745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT                       *pQeB = NULL;
19755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_POINT                       *pQsB = NULL;
19765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    EC_GROUP                       *group = NULL;
19775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnTa;
19785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnDeA;
19795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnDsA;
19805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnXeA;               // x coordinate of ephemeral party A key
19815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnH;
19825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnN;
19835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BIGNUM                         *bnXeB;
19845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
19855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA      *curveData = GetCurveData(curveId);
19865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CRYPT_RESULT              retVal;
19875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(       curveData != NULL && outZ != NULL && dsA != NULL
19885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           &&           deA != NULL && QsB != NULL && QeB != NULL);
19895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
19905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL || curveData == NULL)
19915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
19925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
19935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnTa = BN_CTX_get(context);
19945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnDeA = BN_CTX_get(context);
19955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnDsA = BN_CTX_get(context);
19965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnXeA = BN_CTX_get(context);
19975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnH = BN_CTX_get(context);
19985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnN = BN_CTX_get(context);
19995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   bnXeB = BN_CTX_get(context);
20005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(bnXeB == NULL)
20015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
20025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initialize group parameters and local values of input
20035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((group = EccCurveInit(curveId, context)) == NULL)
20045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
20055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((pQeA = EC_POINT_new(group)) == NULL)
20065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
20075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnDeA, &deA->b);
20085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnDsA, &dsA->b);
20095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnH, curveData->h);
20105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnN, curveData->n);
20115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnXeB, &QeB->x.b);
20125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQeB = EccInitPoint2B(group, QeB, context);
20135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQsB = EccInitPoint2B(group, QsB, context);
20145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute the public ephemeral key pQeA = [de,A]G
20155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(    (retVal = PointMul(group, pQeA, bnDeA, NULL, NULL, context))
20165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      != CRYPT_SUCCESS)
20175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       goto Cleanup;
20185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(EC_POINT_get_affine_coordinates_GFp(group, pQeA, bnXeA, NULL, context) != 1)
20195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
20205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// tA := (ds,A + de,A avf(Xe,A)) mod n (3)
20215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n
20225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Ta = avf(XeA);
20235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_copy(bnTa, bnXeA);
20245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   avfSm2(bnTa, bnN);
20255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(// do Ta = de,A * Ta mod n = deA * avf(XeA) mod n
20265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         !BN_mod_mul(bnTa, bnDeA, bnTa, bnN, context)
20275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // now Ta = dsA + Ta mod n = dsA + deA * avf(XeA) mod n
20285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       || !BN_mod_add(bnTa, bnDsA, bnTa, bnN, context)
20295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
20305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            FAIL(FATAL_ERROR_INTERNAL);
20315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// outZ ? [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4)
20325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Put this in because almost every case of h is == 1 so skip the call when
20335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // not necessary.
20345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!BN_is_one(bnH))
20355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
20365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Cofactor is not 1 so compute Ta := Ta * h mod n
20375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(!BN_mul(bnTa, bnTa, bnH, context))
20385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           FAIL(FATAL_ERROR_INTERNAL);
20395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
20405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Now that 'tA' is (h * 'tA' mod n)
20415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)).
20425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // first, compute XeB = avf(XeB)
20435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   avfSm2(bnXeB, bnN);
20445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // QeB := [XeB]QeB
20455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(     !EC_POINT_mul(group, pQeB, NULL, pQeB, bnXeB, context)
20465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // QeB := QsB + QeB
20475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         || !EC_POINT_add(group, pQeB, pQeB, pQsB, context)
20485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        )
20495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         FAIL(FATAL_ERROR_INTERNAL);
20505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity
20515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(PointMul(group, pQeB, NULL, pQeB, bnTa, context) == CRYPT_SUCCESS)
20525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert BIGNUM E to TPM2B E
20535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Point2B(group, outZ, pQeB, (INT16)BN_num_bytes(bnN), context);
20545679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCleanup:
20555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQeA != NULL) EC_POINT_free(pQeA);
20565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQeB != NULL) EC_POINT_free(pQeB);
20575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQsB != NULL) EC_POINT_free(pQsB);
20585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(group != NULL) EC_GROUP_free(group);
20595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
20605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
20615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return retVal;
20625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
20635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif       //% TPM_ALG_SM2
20645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
20655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
20665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        C_2_2_ECDH()
20675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
20685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified Model,
20695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       C(2, 2, ECC CDH).
20705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
20715679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic CRYPT_RESULT
20725679752bf24c21135884e987c4077e2f7184897Vadim BendeburyC_2_2_ECDH(
20735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *outZ1,         //   OUT: Zs
20745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *outZ2,         //   OUT: Ze
20755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                  curveId,       //   IN: the curve for the computations
20765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *dsA,           //   IN: static private TPM key
20775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER           *deA,           //   IN: ephemeral private TPM key
20785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *QsB,           //   IN: static public party B key
20795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT                *QeB            //   IN: ephemeral public party B key
20805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
20815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2082ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   BIGNUM                        *order;
20835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX                        *context;
20845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_POINT                      *pQ = NULL;
20855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   EC_GROUP                      *group = NULL;
20865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BIGNUM                        *bnD;
20875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT16                          size;
20885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   const ECC_CURVE_DATA          *curveData = GetCurveData(curveId);
20895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   context = BN_CTX_new();
20905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(context == NULL || curveData == NULL)
20915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_ALLOCATION);
20925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_start(context);
2093ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   order = BN_CTX_get(context);
20945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((bnD = BN_CTX_get(context)) == NULL)
20955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
20965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initialize group parameters and local values of input
20975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((group = EccCurveInit(curveId, context)) == NULL)
20985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       FAIL(FATAL_ERROR_INTERNAL);
2099ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   if (!EC_GROUP_get_order(group, order, context))
2100ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr       FAIL(FATAL_ERROR_INTERNAL);
2101ddcb1ce5cc06ae4fc84132aed3e7ec1b611075e8Jocelyn Bohr   size = (INT16)BN_num_bytes(order);
21025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get the static private key of A
21035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnD, &dsA->b);
21045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initialize the static public point from B
21055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pQ = EccInitPoint2B(group, QsB, context);
21065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Do the point multiply for the Zs value
21075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT)
21085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert the Zs value
21095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Point2B(group, outZ1, pQ, size, context);
21105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get the ephemeral private key of A
21115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BnFrom2B(bnD, &deA->b);
21125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initalize the ephemeral public point from B
21135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   PointFrom2B(group, pQ, QeB, context);
21145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Do the point multiply for the Ze value
21155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(PointMul(group, pQ, NULL, pQ, bnD, context) != CRYPT_NO_RESULT)
21165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Convert the Ze value.
21175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       Point2B(group, outZ2, pQ, size, context);
21185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(pQ != NULL) EC_POINT_free(pQ);
21195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(group != NULL) EC_GROUP_free(group);
21205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_end(context);
21215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BN_CTX_free(context);
21225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return CRYPT_SUCCESS;
21235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
21245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//        _cpri__C_2_2_KeyExchange()
21275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function is the dispatch routine for the EC key exchange function that use two ephemeral and two
21295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       static keys.
21305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Return Value                   Meaning
21325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       CRYPT_SCHEME                   scheme is not defined
21345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21355679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
21365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__C_2_2_KeyExchange(
21375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              *outZ1,                //   OUT: a computed point
21385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              *outZ2,                //   OUT: and optional second point
21395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ECC_CURVE                curveId,              //   IN: the curve for the computations
21405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                   scheme,               //   IN: the key exchange scheme
21415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         *dsA,                  //   IN: static private TPM key
21425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER         *deA,                  //   IN: ephemeral private TPM key
21435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              *QsB,                  //   IN: static public party B key
21445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT              *QeB                   //   IN: ephemeral public party B key
21455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
21465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
21475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(   outZ1 != NULL
21485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           && dsA != NULL && deA != NULL
21495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           && QsB != NULL && QeB != NULL);
21505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Initalize the output points so that they are empty until one of the
21515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // functions decides otherwise
21525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outZ1->x.b.size = 0;
21535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outZ1->y.b.size = 0;
21545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(outZ2 != NULL)
21555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
21565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       outZ2->x.b.size = 0;
21575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        outZ2->y.b.size = 0;
21585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
21595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   switch (scheme)
21605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
21615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECDH:
21625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB);
21635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
21645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECMQV
21655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_ECMQV:
21665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB);
21675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
21685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
21695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_SM2
21705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       case TPM_ALG_SM2:
21715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB);
21725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           break;
21735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
21745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       default:
21755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return CRYPT_SCHEME;
21765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
21775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
21785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#else       //%
21795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Stub used when the 2-phase key exchange is not defined so that the linker has something to associate
21815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       with the value in the .def file.
21825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
21835679752bf24c21135884e987c4077e2f7184897Vadim BendeburyLIB_EXPORT CRYPT_RESULT
21845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury_cpri__C_2_2_KeyExchange(
21855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   void
21865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
21875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
21885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return CRYPT_FAIL;
21895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
21905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif //% CC_ZGen_2Phase
21915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif // TPM_ALG_ECC
2192