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(¶ms->prime, PR_FALSE); /* don't free prime */ 357 SECITEM_FreeItem(¶ms->subPrime, PR_FALSE); /* don't free subPrime */ 358 SECITEM_FreeItem(¶ms->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, ¶ms->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, ¶ms->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, ¶ms->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 }