security/nss/lib/softoken/jpakesftk.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "seccomon.h"
     6 #include "secerr.h"
     7 #include "blapi.h"
     8 #include "pkcs11i.h"
     9 #include "softoken.h"
    11 static CK_RV
    12 jpake_mapStatus(SECStatus rv, CK_RV invalidArgsMapping) {
    13     int err;
    14     if (rv == SECSuccess)
    15         return CKR_OK;
    16     err = PORT_GetError();
    17     switch (err) {
    18         /* XXX: SEC_ERROR_INVALID_ARGS might be caused by invalid template
    19             parameters. */
    20         case SEC_ERROR_INVALID_ARGS:  return invalidArgsMapping;
    21         case SEC_ERROR_BAD_SIGNATURE: return CKR_SIGNATURE_INVALID;
    22         case SEC_ERROR_NO_MEMORY:     return CKR_HOST_MEMORY;
    23     }
    24     return CKR_FUNCTION_FAILED;
    25 }
    27 /* If key is not NULL then the gx value will be stored as an attribute with
    28    the type given by the gxAttrType parameter. */
    29 static CK_RV
    30 jpake_Sign(PLArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
    31            const SECItem * signerID, const SECItem * x,
    32            CK_NSS_JPAKEPublicValue * out)
    33 {
    34     SECItem gx, gv, r;
    35     CK_RV crv;
    37     PORT_Assert(arena != NULL);
    39     gx.data = NULL;
    40     gv.data = NULL;
    41     r.data = NULL;
    42     crv = jpake_mapStatus(JPAKE_Sign(arena, pqg, hashType, signerID, x, NULL,
    43                                      NULL, &gx, &gv, &r),
    44                           CKR_MECHANISM_PARAM_INVALID);
    45     if (crv == CKR_OK) {
    46         if ((out->pGX != NULL && out->ulGXLen >= gx.len) ||
    47             (out->pGV != NULL && out->ulGVLen >= gv.len) ||
    48             (out->pR  != NULL && out->ulRLen >= r.len)) {
    49             PORT_Memcpy(out->pGX, gx.data, gx.len); 
    50             PORT_Memcpy(out->pGV, gv.data, gv.len); 
    51             PORT_Memcpy(out->pR, r.data, r.len);
    52             out->ulGXLen = gx.len;
    53             out->ulGVLen = gv.len;
    54             out->ulRLen = r.len;
    55         } else {
    56             crv = CKR_MECHANISM_PARAM_INVALID;
    57         }
    58     } 
    59     return crv;
    60 }
    62 static CK_RV
    63 jpake_Verify(PLArenaPool * arena, const PQGParams * pqg,
    64              HASH_HashType hashType, const SECItem * signerID,
    65              const CK_BYTE * peerIDData, CK_ULONG peerIDLen,
    66              const CK_NSS_JPAKEPublicValue * publicValueIn)
    67 {
    68     SECItem peerID, gx, gv, r;
    69     peerID.data = (unsigned char *) peerIDData; peerID.len = peerIDLen;
    70     gx.data = publicValueIn->pGX; gx.len = publicValueIn->ulGXLen;
    71     gv.data = publicValueIn->pGV; gv.len = publicValueIn->ulGVLen;
    72     r.data = publicValueIn->pR;   r.len = publicValueIn->ulRLen;
    73     return jpake_mapStatus(JPAKE_Verify(arena, pqg, hashType, signerID, &peerID,
    74                                         &gx, &gv, &r),
    75                            CKR_MECHANISM_PARAM_INVALID);
    76 }
    78 #define NUM_ELEM(x) (sizeof (x) / sizeof (x)[0])
    80 /* If the template has the key type set, ensure that it was set to the correct
    81  * value. If the template did not have the key type set, set it to the
    82  * correct value.
    83  */
    84 static CK_RV
    85 jpake_enforceKeyType(SFTKObject * key, CK_KEY_TYPE keyType) {
    86     CK_RV crv;
    87     SFTKAttribute * keyTypeAttr = sftk_FindAttribute(key, CKA_KEY_TYPE);
    88     if (keyTypeAttr != NULL) {
    89         crv = *(CK_KEY_TYPE *)keyTypeAttr->attrib.pValue == keyType
    90             ? CKR_OK
    91             : CKR_TEMPLATE_INCONSISTENT;
    92         sftk_FreeAttribute(keyTypeAttr);
    93     } else {
    94         crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof keyType);
    95     }
    96     return crv;
    97 }
    99 static CK_RV
   100 jpake_MultipleSecItem2Attribute(SFTKObject * key, const SFTKItemTemplate * attrs,
   101                                 size_t attrsCount)
   102 {
   103     size_t i;
   105     for (i = 0; i < attrsCount; ++i) {
   106         CK_RV crv = sftk_forceAttribute(key, attrs[i].type, attrs[i].item->data,
   107                                         attrs[i].item->len);
   108         if (crv != CKR_OK)
   109             return crv;
   110     }
   111     return CKR_OK;
   112 }
   114 CK_RV
   115 jpake_Round1(HASH_HashType hashType, CK_NSS_JPAKERound1Params * params,
   116              SFTKObject * key)
   117 {
   118     CK_RV crv;
   119     PQGParams pqg;
   120     PLArenaPool * arena;
   121     SECItem signerID;
   122     SFTKItemTemplate templateAttrs[] = {
   123         { CKA_PRIME, &pqg.prime },
   124         { CKA_SUBPRIME, &pqg.subPrime },
   125         { CKA_BASE, &pqg.base },
   126         { CKA_NSS_JPAKE_SIGNERID, &signerID }
   127     };
   128     SECItem x2, gx1, gx2;
   129     const SFTKItemTemplate generatedAttrs[] = {
   130         { CKA_NSS_JPAKE_X2,  &x2  },
   131         { CKA_NSS_JPAKE_GX1, &gx1 },
   132         { CKA_NSS_JPAKE_GX2, &gx2 },
   133     };
   134     SECItem x1;
   136     PORT_Assert(params != NULL);
   137     PORT_Assert(key != NULL);
   139     arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
   140     if (arena == NULL)
   141         crv = CKR_HOST_MEMORY;
   143     crv = sftk_MultipleAttribute2SecItem(arena, key, templateAttrs,
   144                                          NUM_ELEM(templateAttrs));
   146     if (crv == CKR_OK && (signerID.data == NULL || signerID.len == 0))
   147         crv = CKR_TEMPLATE_INCOMPLETE;
   149     /* generate x1, g^x1 and the proof of knowledge of x1 */
   150     if (crv == CKR_OK) {
   151         x1.data = NULL;
   152         crv = jpake_mapStatus(DSA_NewRandom(arena, &pqg.subPrime, &x1),
   153                               CKR_TEMPLATE_INCONSISTENT);
   154     }
   155     if (crv == CKR_OK)
   156         crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x1, &params->gx1);
   158     /* generate x2, g^x2 and the proof of knowledge of x2 */
   159     if (crv == CKR_OK) {
   160         x2.data = NULL;
   161         crv = jpake_mapStatus(DSA_NewRandom(arena, &pqg.subPrime, &x2),
   162                               CKR_TEMPLATE_INCONSISTENT);
   163     }
   164     if (crv == CKR_OK)
   165         crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x2, &params->gx2);
   167     /* Save the values needed for round 2 into CKA_VALUE */
   168     if (crv == CKR_OK) {
   169         gx1.data = params->gx1.pGX;
   170         gx1.len = params->gx1.ulGXLen;
   171         gx2.data = params->gx2.pGX;
   172         gx2.len = params->gx2.ulGXLen;
   173         crv = jpake_MultipleSecItem2Attribute(key, generatedAttrs, 
   174                                               NUM_ELEM(generatedAttrs));
   175     }
   177     PORT_FreeArena(arena, PR_TRUE);
   178     return crv;
   179 }
   181 CK_RV
   182 jpake_Round2(HASH_HashType hashType, CK_NSS_JPAKERound2Params * params,
   183              SFTKObject * sourceKey, SFTKObject * key)
   184 {
   185     CK_RV crv;
   186     PLArenaPool * arena;
   187     PQGParams pqg;
   188     SECItem signerID, x2, gx1, gx2;
   189     SFTKItemTemplate sourceAttrs[] = { 
   190         { CKA_PRIME, &pqg.prime },
   191         { CKA_SUBPRIME, &pqg.subPrime },
   192         { CKA_BASE, &pqg.base },
   193         { CKA_NSS_JPAKE_SIGNERID, &signerID },
   194         { CKA_NSS_JPAKE_X2,  &x2 },
   195         { CKA_NSS_JPAKE_GX1, &gx1 },
   196         { CKA_NSS_JPAKE_GX2, &gx2 },
   197     };
   198     SECItem x2s, gx3, gx4;
   199     const SFTKItemTemplate copiedAndGeneratedAttrs[] = {
   200         { CKA_NSS_JPAKE_SIGNERID, &signerID },
   201         { CKA_PRIME, &pqg.prime },
   202         { CKA_SUBPRIME, &pqg.subPrime },
   203         { CKA_NSS_JPAKE_X2,  &x2  },
   204         { CKA_NSS_JPAKE_X2S, &x2s },
   205         { CKA_NSS_JPAKE_GX1, &gx1 },
   206         { CKA_NSS_JPAKE_GX2, &gx2 },
   207         { CKA_NSS_JPAKE_GX3, &gx3 },
   208         { CKA_NSS_JPAKE_GX4, &gx4 }
   209     };
   210     SECItem peerID;
   212     PORT_Assert(params != NULL);
   213     PORT_Assert(sourceKey != NULL);
   214     PORT_Assert(key != NULL);
   216     arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
   217     if (arena == NULL)
   218         crv = CKR_HOST_MEMORY;
   220     /* TODO: check CKK_NSS_JPAKE_ROUND1 */
   222     crv = sftk_MultipleAttribute2SecItem(arena, sourceKey, sourceAttrs,
   223                                          NUM_ELEM(sourceAttrs));
   225     /* Get the peer's ID out of the template and sanity-check it. */
   226     if (crv == CKR_OK)
   227         crv = sftk_Attribute2SecItem(arena, &peerID, key,
   228                                      CKA_NSS_JPAKE_PEERID);
   229     if (crv == CKR_OK && (peerID.data == NULL || peerID.len == 0))
   230         crv = CKR_TEMPLATE_INCOMPLETE;
   231     if (crv == CKR_OK && SECITEM_CompareItem(&signerID, &peerID) == SECEqual)
   232         crv = CKR_TEMPLATE_INCONSISTENT;
   234     /* Verify zero-knowledge proofs for g^x3 and g^x4 */
   235     if (crv == CKR_OK)
   236         crv = jpake_Verify(arena, &pqg, hashType, &signerID,
   237                            peerID.data, peerID.len, &params->gx3);
   238     if (crv == CKR_OK)
   239         crv = jpake_Verify(arena, &pqg, hashType, &signerID,
   240                            peerID.data, peerID.len, &params->gx4);
   242     /* Calculate the base and x2s for A=base^x2s */
   243     if (crv == CKR_OK) {
   244         SECItem s;
   245         s.data = params->pSharedKey;
   246         s.len = params->ulSharedKeyLen;
   247         gx3.data = params->gx3.pGX;
   248         gx3.len = params->gx3.ulGXLen;
   249         gx4.data = params->gx4.pGX;
   250         gx4.len = params->gx4.ulGXLen;
   251         pqg.base.data = NULL;
   252         x2s.data = NULL;
   253         crv = jpake_mapStatus(JPAKE_Round2(arena, &pqg.prime, &pqg.subPrime,
   254                                            &gx1, &gx3, &gx4, &pqg.base, 
   255                                            &x2, &s, &x2s),
   256                               CKR_MECHANISM_PARAM_INVALID);
   257     }
   259     /* Generate A=base^x2s and its zero-knowledge proof. */
   260     if (crv == CKR_OK)
   261         crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x2s, &params->A);
   263     /* Copy P and Q from the ROUND1 key to the ROUND2 key and save the values
   264        needed for the final key material derivation into CKA_VALUE. */
   265     if (crv == CKR_OK)
   266         crv = sftk_forceAttribute(key, CKA_PRIME, pqg.prime.data,
   267                                   pqg.prime.len);
   268     if (crv == CKR_OK)
   269         crv = sftk_forceAttribute(key, CKA_SUBPRIME, pqg.subPrime.data,
   270                                   pqg.subPrime.len);
   271     if (crv == CKR_OK) {
   272         crv = jpake_MultipleSecItem2Attribute(key, copiedAndGeneratedAttrs,
   273                                               NUM_ELEM(copiedAndGeneratedAttrs));
   274     }
   276     if (crv == CKR_OK)
   277         crv = jpake_enforceKeyType(key, CKK_NSS_JPAKE_ROUND2);
   279     PORT_FreeArena(arena, PR_TRUE);
   280     return crv;
   281 }
   283 CK_RV
   284 jpake_Final(HASH_HashType hashType, const CK_NSS_JPAKEFinalParams * param,
   285             SFTKObject * sourceKey, SFTKObject * key)
   286 {
   287     PLArenaPool * arena;
   288     SECItem K;
   289     PQGParams pqg;
   290     CK_RV crv;
   291     SECItem peerID, signerID, x2s, x2, gx1, gx2, gx3, gx4;
   292     SFTKItemTemplate sourceAttrs[] = {
   293         { CKA_NSS_JPAKE_PEERID, &peerID },
   294         { CKA_NSS_JPAKE_SIGNERID, &signerID },
   295         { CKA_PRIME, &pqg.prime },
   296         { CKA_SUBPRIME, &pqg.subPrime },
   297         { CKA_NSS_JPAKE_X2,  &x2  },
   298         { CKA_NSS_JPAKE_X2S, &x2s },
   299         { CKA_NSS_JPAKE_GX1, &gx1 },
   300         { CKA_NSS_JPAKE_GX2, &gx2 },
   301         { CKA_NSS_JPAKE_GX3, &gx3 },
   302         { CKA_NSS_JPAKE_GX4, &gx4 }
   303     };
   305     PORT_Assert(param != NULL);
   306     PORT_Assert(sourceKey != NULL);
   307     PORT_Assert(key != NULL);
   309     arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
   310     if (arena == NULL)
   311         crv = CKR_HOST_MEMORY;
   313     /* TODO: verify key type CKK_NSS_JPAKE_ROUND2 */
   315     crv = sftk_MultipleAttribute2SecItem(arena, sourceKey, sourceAttrs,
   316                                          NUM_ELEM(sourceAttrs));
   318     /* Calculate base for B=base^x4s */
   319     if (crv == CKR_OK) {
   320         pqg.base.data = NULL;
   321         crv = jpake_mapStatus(JPAKE_Round2(arena, &pqg.prime, &pqg.subPrime,
   322                                            &gx1, &gx2, &gx3, &pqg.base,
   323                                            NULL, NULL, NULL),
   324                               CKR_MECHANISM_PARAM_INVALID);
   325     }
   327     /* Verify zero-knowledge proof for B */
   328     if (crv == CKR_OK)
   329         crv = jpake_Verify(arena, &pqg, hashType, &signerID,
   330                            peerID.data, peerID.len, &param->B);
   331     if (crv == CKR_OK) {
   332         SECItem B;
   333         B.data = param->B.pGX;
   334         B.len = param->B.ulGXLen;
   335         K.data = NULL;
   336         crv = jpake_mapStatus(JPAKE_Final(arena, &pqg.prime, &pqg.subPrime,
   337                                           &x2, &gx4, &x2s, &B, &K),
   338                               CKR_MECHANISM_PARAM_INVALID);
   339     }
   341     /* Save key material into CKA_VALUE. */
   342     if (crv == CKR_OK)
   343         crv = sftk_forceAttribute(key, CKA_VALUE, K.data, K.len);
   345     if (crv == CKR_OK)
   346         crv = jpake_enforceKeyType(key, CKK_GENERIC_SECRET);
   348     PORT_FreeArena(arena, PR_TRUE);
   349     return crv;
   350 }

mercurial