tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pk11pqg.c (17457B)


      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/. */
      4 /* Thse functions are stub functions which will get replaced with calls through
      5 * PKCS #11.
      6 */
      7 
      8 #include "pk11func.h"
      9 #include "secmod.h"
     10 #include "secmodi.h"
     11 #include "secmodti.h"
     12 #include "pkcs11t.h"
     13 #include "pk11pqg.h"
     14 #include "secerr.h"
     15 
     16 /* Generate PQGParams and PQGVerify structs.
     17 * Length of P specified by L.
     18 *   if L is greater than 1024 then the resulting verify parameters will be
     19 *   DSA2.
     20 * Length of Q specified by N. If zero, The PKCS #11 module will
     21 *   pick an appropriately sized Q for P. If N is specified and L = 1024, then
     22 *   the resulting verify parameters will be DSA2, Otherwise DSA1 parameters
     23 *   will be returned.
     24 * Length of SEED in bytes specified in seedBytes.
     25 *
     26 * The underlying PKCS #11 module will check the values for L, N,
     27 * and seedBytes. The rules for softoken are:
     28 *
     29 * If L <= 1024, then L must be between 512 and 1024 in increments of 64 bits.
     30 * If L <= 1024, then N must be 0 or 160.
     31 * If L >= 1024, then L and N must match the following table:
     32 *   L=1024   N=0 or 160
     33 *   L=2048   N=0 or 224
     34 *   L=2048   N=256
     35 *   L=3072   N=0 or 256
     36 * if L <= 1024
     37 *   seedBbytes must be in the range [20..256].
     38 * if L >= 1024
     39 *   seedBbytes must be in the range [20..L/16].
     40 */
     41 extern SECStatus
     42 PK11_PQG_ParamGenV2(unsigned int L, unsigned int N,
     43                    unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy)
     44 {
     45    PK11SlotInfo *slot = NULL;
     46    CK_ATTRIBUTE genTemplate[5];
     47    CK_ATTRIBUTE *attrs = genTemplate;
     48    int count = sizeof(genTemplate) / sizeof(genTemplate[0]);
     49    CK_MECHANISM mechanism;
     50    CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE;
     51    CK_RV crv;
     52    CK_ATTRIBUTE pTemplate[] = {
     53        { CKA_PRIME, NULL, 0 },
     54        { CKA_SUBPRIME, NULL, 0 },
     55        { CKA_BASE, NULL, 0 },
     56    };
     57    CK_ATTRIBUTE vTemplate[] = {
     58        { CKA_NSS_PQG_COUNTER, NULL, 0 },
     59        { CKA_NSS_PQG_SEED, NULL, 0 },
     60        { CKA_NSS_PQG_H, NULL, 0 },
     61    };
     62    CK_ULONG primeBits = L;
     63    CK_ULONG subPrimeBits = N;
     64    int pTemplateCount = sizeof(pTemplate) / sizeof(pTemplate[0]);
     65    int vTemplateCount = sizeof(vTemplate) / sizeof(vTemplate[0]);
     66    PLArenaPool *parena = NULL;
     67    PLArenaPool *varena = NULL;
     68    PQGParams *params = NULL;
     69    PQGVerify *verify = NULL;
     70    CK_ULONG seedBits = seedBytes * 8;
     71 
     72    *pParams = NULL;
     73    *pVfy = NULL;
     74 
     75    if (primeBits == (CK_ULONG)-1) {
     76        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     77        goto loser;
     78    }
     79    PK11_SETATTRS(attrs, CKA_PRIME_BITS, &primeBits, sizeof(primeBits));
     80    attrs++;
     81    if (subPrimeBits != 0) {
     82        PK11_SETATTRS(attrs, CKA_SUB_PRIME_BITS,
     83                      &subPrimeBits, sizeof(subPrimeBits));
     84        attrs++;
     85    }
     86    if (seedBits != 0) {
     87        PK11_SETATTRS(attrs, CKA_NSS_PQG_SEED_BITS,
     88                      &seedBits, sizeof(seedBits));
     89        attrs++;
     90    }
     91    count = attrs - genTemplate;
     92    PR_ASSERT(count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE));
     93 
     94    slot = PK11_GetInternalSlot();
     95    if (slot == NULL) {
     96        /* set error */
     97        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
     98        goto loser;
     99    }
    100 
    101    /* make sure the internal slot can handle DSA2 type parameters. */
    102    if (primeBits > 1024) {
    103        CK_MECHANISM_INFO mechanism_info;
    104 
    105        if (!slot->isThreadSafe)
    106            PK11_EnterSlotMonitor(slot);
    107        crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
    108                                                    CKM_DSA_PARAMETER_GEN,
    109                                                    &mechanism_info);
    110        if (!slot->isThreadSafe)
    111            PK11_ExitSlotMonitor(slot);
    112        /* a bug in the old softoken left CKM_DSA_PARAMETER_GEN off of the
    113         * mechanism List. If we get a failure asking for this value, we know
    114         * it can't handle DSA2 */
    115        if ((crv != CKR_OK) || (mechanism_info.ulMaxKeySize < primeBits)) {
    116            PK11_FreeSlot(slot);
    117            slot = PK11_GetBestSlotWithAttributes(CKM_DSA_PARAMETER_GEN, 0,
    118                                                  primeBits, NULL);
    119            if (slot == NULL) {
    120                PORT_SetError(SEC_ERROR_NO_TOKEN); /* can happen */
    121                goto loser;
    122            }
    123            /* ditch seedBits in this case, they are NSS specific and at
    124             * this point we have a token that claims to handle DSA2 */
    125            if (seedBits) {
    126                attrs--;
    127            }
    128        }
    129    }
    130 
    131    /* Initialize the Key Gen Mechanism */
    132    mechanism.mechanism = CKM_DSA_PARAMETER_GEN;
    133    mechanism.pParameter = NULL;
    134    mechanism.ulParameterLen = 0;
    135 
    136    PK11_EnterSlotMonitor(slot);
    137    crv = PK11_GETTAB(slot)->C_GenerateKey(slot->session,
    138                                           &mechanism, genTemplate, count, &objectID);
    139    PK11_ExitSlotMonitor(slot);
    140 
    141    if (crv != CKR_OK) {
    142        PORT_SetError(PK11_MapError(crv));
    143        goto loser;
    144    }
    145 
    146    parena = PORT_NewArena(60);
    147    if (!parena) {
    148        goto loser;
    149    }
    150 
    151    crv = PK11_GetAttributes(parena, slot, objectID, pTemplate, pTemplateCount);
    152    if (crv != CKR_OK) {
    153        PORT_SetError(PK11_MapError(crv));
    154        goto loser;
    155    }
    156 
    157    params = (PQGParams *)PORT_ArenaAlloc(parena, sizeof(PQGParams));
    158    if (params == NULL) {
    159        goto loser;
    160    }
    161 
    162    /* fill in Params */
    163    params->arena = parena;
    164    params->prime.type = siUnsignedInteger;
    165    params->prime.data = pTemplate[0].pValue;
    166    params->prime.len = pTemplate[0].ulValueLen;
    167    params->subPrime.type = siUnsignedInteger;
    168    params->subPrime.data = pTemplate[1].pValue;
    169    params->subPrime.len = pTemplate[1].ulValueLen;
    170    params->base.type = siUnsignedInteger;
    171    params->base.data = pTemplate[2].pValue;
    172    params->base.len = pTemplate[2].ulValueLen;
    173 
    174    varena = PORT_NewArena(60);
    175    if (!varena) {
    176        goto loser;
    177    }
    178 
    179    crv = PK11_GetAttributes(varena, slot, objectID, vTemplate, vTemplateCount);
    180    if (crv != CKR_OK) {
    181        PORT_SetError(PK11_MapError(crv));
    182        goto loser;
    183    }
    184 
    185    verify = (PQGVerify *)PORT_ArenaAlloc(varena, sizeof(PQGVerify));
    186    if (verify == NULL) {
    187        goto loser;
    188    }
    189    /* fill in Params */
    190    verify->arena = varena;
    191    verify->counter = (unsigned int)(*(CK_ULONG *)vTemplate[0].pValue);
    192    verify->seed.type = siUnsignedInteger;
    193    verify->seed.data = vTemplate[1].pValue;
    194    verify->seed.len = vTemplate[1].ulValueLen;
    195    verify->h.type = siUnsignedInteger;
    196    verify->h.data = vTemplate[2].pValue;
    197    verify->h.len = vTemplate[2].ulValueLen;
    198 
    199    PK11_DestroyObject(slot, objectID);
    200    PK11_FreeSlot(slot);
    201 
    202    *pParams = params;
    203    *pVfy = verify;
    204 
    205    return SECSuccess;
    206 
    207 loser:
    208    if (objectID != CK_INVALID_HANDLE) {
    209        PK11_DestroyObject(slot, objectID);
    210    }
    211    if (parena != NULL) {
    212        PORT_FreeArena(parena, PR_FALSE);
    213    }
    214    if (varena != NULL) {
    215        PORT_FreeArena(varena, PR_FALSE);
    216    }
    217    if (slot) {
    218        PK11_FreeSlot(slot);
    219    }
    220    return SECFailure;
    221 }
    222 
    223 /* Generate PQGParams and PQGVerify structs.
    224 * Length of P specified by j.  Length of h will match length of P.
    225 * Length of SEED in bytes specified in seedBytes.
    226 * seedBbytes must be in the range [20..255] or an error will result.
    227 */
    228 extern SECStatus
    229 PK11_PQG_ParamGenSeedLen(unsigned int j, unsigned int seedBytes,
    230                         PQGParams **pParams, PQGVerify **pVfy)
    231 {
    232    unsigned int primeBits = PQG_INDEX_TO_PBITS(j);
    233    return PK11_PQG_ParamGenV2(primeBits, 0, seedBytes, pParams, pVfy);
    234 }
    235 
    236 /* Generate PQGParams and PQGVerify structs.
    237 * Length of seed and length of h both equal length of P.
    238 * All lengths are specified by "j", according to the table above.
    239 */
    240 extern SECStatus
    241 PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy)
    242 {
    243    unsigned int primeBits = PQG_INDEX_TO_PBITS(j);
    244    return PK11_PQG_ParamGenV2(primeBits, 0, 0, pParams, pVfy);
    245 }
    246 
    247 /*  Test PQGParams for validity as DSS PQG values.
    248 *  If vfy is non-NULL, test PQGParams to make sure they were generated
    249 *       using the specified seed, counter, and h values.
    250 *
    251 *  Return value indicates whether Verification operation ran successfully
    252 *  to completion, but does not indicate if PQGParams are valid or not.
    253 *  If return value is SECSuccess, then *pResult has these meanings:
    254 *       SECSuccess: PQGParams are valid.
    255 *       SECFailure: PQGParams are invalid.
    256 */
    257 
    258 extern SECStatus
    259 PK11_PQG_VerifyParams(const PQGParams *params, const PQGVerify *vfy,
    260                      SECStatus *result)
    261 {
    262    CK_ATTRIBUTE keyTempl[] = {
    263        { CKA_CLASS, NULL, 0 },
    264        { CKA_KEY_TYPE, NULL, 0 },
    265        { CKA_PRIME, NULL, 0 },
    266        { CKA_SUBPRIME, NULL, 0 },
    267        { CKA_BASE, NULL, 0 },
    268        { CKA_TOKEN, NULL, 0 },
    269        { CKA_NSS_PQG_COUNTER, NULL, 0 },
    270        { CKA_NSS_PQG_SEED, NULL, 0 },
    271        { CKA_NSS_PQG_H, NULL, 0 },
    272    };
    273    CK_ATTRIBUTE *attrs;
    274    CK_BBOOL ckfalse = CK_FALSE;
    275    CK_OBJECT_CLASS class = CKO_DOMAIN_PARAMETERS;
    276    CK_KEY_TYPE keyType = CKK_DSA;
    277    SECStatus rv = SECSuccess;
    278    PK11SlotInfo *slot;
    279    int keyCount;
    280    CK_OBJECT_HANDLE objectID;
    281    CK_ULONG counter;
    282    CK_RV crv;
    283 
    284    attrs = keyTempl;
    285    PK11_SETATTRS(attrs, CKA_CLASS, &class, sizeof(class));
    286    attrs++;
    287    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
    288    attrs++;
    289    PK11_SETATTRS(attrs, CKA_PRIME, params->prime.data,
    290                  params->prime.len);
    291    attrs++;
    292    PK11_SETATTRS(attrs, CKA_SUBPRIME, params->subPrime.data,
    293                  params->subPrime.len);
    294    attrs++;
    295    if (params->base.len) {
    296        PK11_SETATTRS(attrs, CKA_BASE, params->base.data, params->base.len);
    297        attrs++;
    298    }
    299    PK11_SETATTRS(attrs, CKA_TOKEN, &ckfalse, sizeof(ckfalse));
    300    attrs++;
    301    if (vfy) {
    302        if (vfy->counter != -1) {
    303            counter = vfy->counter;
    304            PK11_SETATTRS(attrs, CKA_NSS_PQG_COUNTER,
    305                          &counter, sizeof(counter));
    306            attrs++;
    307        }
    308        PK11_SETATTRS(attrs, CKA_NSS_PQG_SEED,
    309                      vfy->seed.data, vfy->seed.len);
    310        attrs++;
    311        if (vfy->h.len) {
    312            PK11_SETATTRS(attrs, CKA_NSS_PQG_H,
    313                          vfy->h.data, vfy->h.len);
    314            attrs++;
    315        }
    316    }
    317 
    318    keyCount = attrs - keyTempl;
    319    PORT_Assert(keyCount <= sizeof(keyTempl) / sizeof(keyTempl[0]));
    320 
    321    slot = PK11_GetInternalSlot();
    322    if (slot == NULL) {
    323        return SECFailure;
    324    }
    325 
    326    PK11_EnterSlotMonitor(slot);
    327    crv = PK11_GETTAB(slot)->C_CreateObject(slot->session, keyTempl, keyCount,
    328                                            &objectID);
    329    PK11_ExitSlotMonitor(slot);
    330 
    331    /* throw away the keys, we only wanted the return code */
    332    PK11_DestroyObject(slot, objectID);
    333    PK11_FreeSlot(slot);
    334 
    335    *result = SECSuccess;
    336    if (crv == CKR_ATTRIBUTE_VALUE_INVALID) {
    337        *result = SECFailure;
    338    } else if (crv != CKR_OK) {
    339        PORT_SetError(PK11_MapError(crv));
    340        rv = SECFailure;
    341    }
    342    return rv;
    343 }
    344 
    345 /**************************************************************************
    346 *  Free the PQGParams struct and the things it points to.                *
    347 **************************************************************************/
    348 extern void
    349 PK11_PQG_DestroyParams(PQGParams *params)
    350 {
    351    if (params == NULL)
    352        return;
    353    if (params->arena != NULL) {
    354        PORT_FreeArena(params->arena, PR_FALSE); /* don't zero it */
    355    } else {
    356        SECITEM_FreeItem(&params->prime, PR_FALSE);    /* don't free prime */
    357        SECITEM_FreeItem(&params->subPrime, PR_FALSE); /* don't free subPrime */
    358        SECITEM_FreeItem(&params->base, PR_FALSE);     /* don't free base */
    359        PORT_Free(params);
    360    }
    361 }
    362 
    363 /**************************************************************************
    364 *  Free the PQGVerify struct and the things it points to.                *
    365 **************************************************************************/
    366 extern void
    367 PK11_PQG_DestroyVerify(PQGVerify *vfy)
    368 {
    369    if (vfy == NULL)
    370        return;
    371    if (vfy->arena != NULL) {
    372        PORT_FreeArena(vfy->arena, PR_FALSE); /* don't zero it */
    373    } else {
    374        SECITEM_FreeItem(&vfy->seed, PR_FALSE); /* don't free seed */
    375        SECITEM_FreeItem(&vfy->h, PR_FALSE);    /* don't free h */
    376        PORT_Free(vfy);
    377    }
    378 }
    379 
    380 #define PQG_DEFAULT_CHUNKSIZE 2048 /* bytes */
    381 
    382 /**************************************************************************
    383 *  Return a pointer to a new PQGParams struct that is constructed from   *
    384 *  copies of the arguments passed in.                                    *
    385 *  Return NULL on failure.                                               *
    386 **************************************************************************/
    387 extern PQGParams *
    388 PK11_PQG_NewParams(const SECItem *prime, const SECItem *subPrime,
    389                   const SECItem *base)
    390 {
    391    PLArenaPool *arena;
    392    PQGParams *dest;
    393    SECStatus status;
    394 
    395    arena = PORT_NewArena(PQG_DEFAULT_CHUNKSIZE);
    396    if (arena == NULL)
    397        goto loser;
    398 
    399    dest = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
    400    if (dest == NULL)
    401        goto loser;
    402 
    403    dest->arena = arena;
    404 
    405    status = SECITEM_CopyItem(arena, &dest->prime, prime);
    406    if (status != SECSuccess)
    407        goto loser;
    408 
    409    status = SECITEM_CopyItem(arena, &dest->subPrime, subPrime);
    410    if (status != SECSuccess)
    411        goto loser;
    412 
    413    status = SECITEM_CopyItem(arena, &dest->base, base);
    414    if (status != SECSuccess)
    415        goto loser;
    416 
    417    return dest;
    418 
    419 loser:
    420    if (arena != NULL)
    421        PORT_FreeArena(arena, PR_FALSE);
    422    return NULL;
    423 }
    424 
    425 /**************************************************************************
    426 * Fills in caller's "prime" SECItem with the prime value in params.
    427 * Contents can be freed by calling SECITEM_FreeItem(prime, PR_FALSE);
    428 **************************************************************************/
    429 extern SECStatus
    430 PK11_PQG_GetPrimeFromParams(const PQGParams *params, SECItem *prime)
    431 {
    432    return SECITEM_CopyItem(NULL, prime, &params->prime);
    433 }
    434 
    435 /**************************************************************************
    436 * Fills in caller's "subPrime" SECItem with the prime value in params.
    437 * Contents can be freed by calling SECITEM_FreeItem(subPrime, PR_FALSE);
    438 **************************************************************************/
    439 extern SECStatus
    440 PK11_PQG_GetSubPrimeFromParams(const PQGParams *params, SECItem *subPrime)
    441 {
    442    return SECITEM_CopyItem(NULL, subPrime, &params->subPrime);
    443 }
    444 
    445 /**************************************************************************
    446 * Fills in caller's "base" SECItem with the base value in params.
    447 * Contents can be freed by calling SECITEM_FreeItem(base, PR_FALSE);
    448 **************************************************************************/
    449 extern SECStatus
    450 PK11_PQG_GetBaseFromParams(const PQGParams *params, SECItem *base)
    451 {
    452    return SECITEM_CopyItem(NULL, base, &params->base);
    453 }
    454 
    455 /**************************************************************************
    456 *  Return a pointer to a new PQGVerify struct that is constructed from   *
    457 *  copies of the arguments passed in.                                    *
    458 *  Return NULL on failure.                                               *
    459 **************************************************************************/
    460 extern PQGVerify *
    461 PK11_PQG_NewVerify(unsigned int counter, const SECItem *seed,
    462                   const SECItem *h)
    463 {
    464    PLArenaPool *arena;
    465    PQGVerify *dest;
    466    SECStatus status;
    467 
    468    arena = PORT_NewArena(PQG_DEFAULT_CHUNKSIZE);
    469    if (arena == NULL)
    470        goto loser;
    471 
    472    dest = (PQGVerify *)PORT_ArenaZAlloc(arena, sizeof(PQGVerify));
    473    if (dest == NULL)
    474        goto loser;
    475 
    476    dest->arena = arena;
    477    dest->counter = counter;
    478 
    479    status = SECITEM_CopyItem(arena, &dest->seed, seed);
    480    if (status != SECSuccess)
    481        goto loser;
    482 
    483    status = SECITEM_CopyItem(arena, &dest->h, h);
    484    if (status != SECSuccess)
    485        goto loser;
    486 
    487    return dest;
    488 
    489 loser:
    490    if (arena != NULL)
    491        PORT_FreeArena(arena, PR_FALSE);
    492    return NULL;
    493 }
    494 
    495 /**************************************************************************
    496 * Returns "counter" value from the PQGVerify.
    497 **************************************************************************/
    498 extern unsigned int
    499 PK11_PQG_GetCounterFromVerify(const PQGVerify *verify)
    500 {
    501    return verify->counter;
    502 }
    503 
    504 /**************************************************************************
    505 * Fills in caller's "seed" SECItem with the seed value in verify.
    506 * Contents can be freed by calling SECITEM_FreeItem(seed, PR_FALSE);
    507 **************************************************************************/
    508 extern SECStatus
    509 PK11_PQG_GetSeedFromVerify(const PQGVerify *verify, SECItem *seed)
    510 {
    511    return SECITEM_CopyItem(NULL, seed, &verify->seed);
    512 }
    513 
    514 /**************************************************************************
    515 * Fills in caller's "h" SECItem with the h value in verify.
    516 * Contents can be freed by calling SECITEM_FreeItem(h, PR_FALSE);
    517 **************************************************************************/
    518 extern SECStatus
    519 PK11_PQG_GetHFromVerify(const PQGVerify *verify, SECItem *h)
    520 {
    521    return SECITEM_CopyItem(NULL, h, &verify->h);
    522 }