security/nss/lib/freebl/pqg.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

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * PQG parameter generation/verification. Based on FIPS 186-3.
michael@0 7 */
michael@0 8 #ifdef FREEBL_NO_DEPEND
michael@0 9 #include "stubs.h"
michael@0 10 #endif
michael@0 11
michael@0 12 #include "prerr.h"
michael@0 13 #include "secerr.h"
michael@0 14
michael@0 15 #include "prtypes.h"
michael@0 16 #include "blapi.h"
michael@0 17 #include "secitem.h"
michael@0 18 #include "mpi.h"
michael@0 19 #include "mpprime.h"
michael@0 20 #include "mplogic.h"
michael@0 21 #include "secmpi.h"
michael@0 22
michael@0 23 #define MAX_ITERATIONS 1000 /* Maximum number of iterations of primegen */
michael@0 24
michael@0 25 typedef enum {
michael@0 26 FIPS186_1_TYPE, /* Probablistic */
michael@0 27 FIPS186_3_TYPE, /* Probablistic */
michael@0 28 FIPS186_3_ST_TYPE /* Shawe-Taylor provable */
michael@0 29 } pqgGenType;
michael@0 30
michael@0 31 /*
michael@0 32 * These test iterations are quite a bit larger than we previously had.
michael@0 33 * This is because FIPS 186-3 is worried about the primes in PQG generation.
michael@0 34 * It may be possible to purposefully construct composites which more
michael@0 35 * iterations of Miller-Rabin than the for your normal randomly selected
michael@0 36 * numbers.There are 3 ways to counter this: 1) use one of the cool provably
michael@0 37 * prime algorithms (which would require a lot more work than DSA-2 deservers.
michael@0 38 * 2) add a Lucas primality test (which requires coding a Lucas primality test,
michael@0 39 * or 3) use a larger M-R test count. I chose the latter. It increases the time
michael@0 40 * that it takes to prove the selected prime, but it shouldn't increase the
michael@0 41 * overall time to run the algorithm (non-primes should still faile M-R
michael@0 42 * realively quickly). If you want to get that last bit of performance,
michael@0 43 * implement Lucas and adjust these two functions. See FIPS 186-3 Appendix C
michael@0 44 * and F for more information.
michael@0 45 */
michael@0 46 int prime_testcount_p(int L, int N)
michael@0 47 {
michael@0 48 switch (L) {
michael@0 49 case 1024:
michael@0 50 return 40;
michael@0 51 case 2048:
michael@0 52 return 56;
michael@0 53 case 3072:
michael@0 54 return 64;
michael@0 55 default:
michael@0 56 break;
michael@0 57 }
michael@0 58 return 50; /* L = 512-960 */
michael@0 59 }
michael@0 60
michael@0 61 /* The q numbers are different if you run M-R followd by Lucas. I created
michael@0 62 * a separate function so if someone wanted to add the Lucas check, they
michael@0 63 * could do so fairly easily */
michael@0 64 int prime_testcount_q(int L, int N)
michael@0 65 {
michael@0 66 return prime_testcount_p(L,N);
michael@0 67 }
michael@0 68
michael@0 69 /*
michael@0 70 * generic function to make sure our input matches DSA2 requirements
michael@0 71 * this gives us one place to go if we need to bump the requirements in the
michael@0 72 * future.
michael@0 73 */
michael@0 74 static SECStatus
michael@0 75 pqg_validate_dsa2(unsigned int L, unsigned int N)
michael@0 76 {
michael@0 77
michael@0 78 switch (L) {
michael@0 79 case 1024:
michael@0 80 if (N != DSA1_Q_BITS) {
michael@0 81 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 82 return SECFailure;
michael@0 83 }
michael@0 84 break;
michael@0 85 case 2048:
michael@0 86 if ((N != 224) && (N != 256)) {
michael@0 87 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 88 return SECFailure;
michael@0 89 }
michael@0 90 break;
michael@0 91 case 3072:
michael@0 92 if (N != 256) {
michael@0 93 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 94 return SECFailure;
michael@0 95 }
michael@0 96 break;
michael@0 97 default:
michael@0 98 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 99 return SECFailure;
michael@0 100 }
michael@0 101 return SECSuccess;
michael@0 102 }
michael@0 103
michael@0 104 static unsigned int
michael@0 105 pqg_get_default_N(unsigned int L)
michael@0 106 {
michael@0 107 unsigned int N = 0;
michael@0 108 switch (L) {
michael@0 109 case 1024:
michael@0 110 N = DSA1_Q_BITS;
michael@0 111 break;
michael@0 112 case 2048:
michael@0 113 N = 224;
michael@0 114 break;
michael@0 115 case 3072:
michael@0 116 N = 256;
michael@0 117 break;
michael@0 118 default:
michael@0 119 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 120 break; /* N already set to zero */
michael@0 121 }
michael@0 122 return N;
michael@0 123 }
michael@0 124
michael@0 125 /*
michael@0 126 * Select the lowest hash algorithm usable
michael@0 127 */
michael@0 128 static HASH_HashType
michael@0 129 getFirstHash(unsigned int L, unsigned int N)
michael@0 130 {
michael@0 131 if (N < 224) {
michael@0 132 return HASH_AlgSHA1;
michael@0 133 }
michael@0 134 if (N < 256) {
michael@0 135 return HASH_AlgSHA224;
michael@0 136 }
michael@0 137 if (N < 384) {
michael@0 138 return HASH_AlgSHA256;
michael@0 139 }
michael@0 140 if (N < 512) {
michael@0 141 return HASH_AlgSHA384;
michael@0 142 }
michael@0 143 return HASH_AlgSHA512;
michael@0 144 }
michael@0 145
michael@0 146 /*
michael@0 147 * find the next usable hash algorthim
michael@0 148 */
michael@0 149 static HASH_HashType
michael@0 150 getNextHash(HASH_HashType hashtype)
michael@0 151 {
michael@0 152 switch (hashtype) {
michael@0 153 case HASH_AlgSHA1:
michael@0 154 hashtype = HASH_AlgSHA224;
michael@0 155 break;
michael@0 156 case HASH_AlgSHA224:
michael@0 157 hashtype = HASH_AlgSHA256;
michael@0 158 break;
michael@0 159 case HASH_AlgSHA256:
michael@0 160 hashtype = HASH_AlgSHA384;
michael@0 161 break;
michael@0 162 case HASH_AlgSHA384:
michael@0 163 hashtype = HASH_AlgSHA512;
michael@0 164 break;
michael@0 165 case HASH_AlgSHA512:
michael@0 166 default:
michael@0 167 hashtype = HASH_AlgTOTAL;
michael@0 168 break;
michael@0 169 }
michael@0 170 return hashtype;
michael@0 171 }
michael@0 172
michael@0 173 static unsigned int
michael@0 174 HASH_ResultLen(HASH_HashType type)
michael@0 175 {
michael@0 176 const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
michael@0 177 if (hash_obj == NULL) {
michael@0 178 return 0;
michael@0 179 }
michael@0 180 return hash_obj->length;
michael@0 181 }
michael@0 182
michael@0 183 static SECStatus
michael@0 184 HASH_HashBuf(HASH_HashType type, unsigned char *dest,
michael@0 185 const unsigned char *src, PRUint32 src_len)
michael@0 186 {
michael@0 187 const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
michael@0 188 void *hashcx = NULL;
michael@0 189 unsigned int dummy;
michael@0 190
michael@0 191 if (hash_obj == NULL) {
michael@0 192 return SECFailure;
michael@0 193 }
michael@0 194
michael@0 195 hashcx = hash_obj->create();
michael@0 196 if (hashcx == NULL) {
michael@0 197 return SECFailure;
michael@0 198 }
michael@0 199 hash_obj->begin(hashcx);
michael@0 200 hash_obj->update(hashcx,src,src_len);
michael@0 201 hash_obj->end(hashcx,dest, &dummy, hash_obj->length);
michael@0 202 hash_obj->destroy(hashcx, PR_TRUE);
michael@0 203 return SECSuccess;
michael@0 204 }
michael@0 205
michael@0 206 unsigned int
michael@0 207 PQG_GetLength(const SECItem *obj)
michael@0 208 {
michael@0 209 unsigned int len = obj->len;
michael@0 210
michael@0 211 if (obj->data == NULL) {
michael@0 212 return 0;
michael@0 213 }
michael@0 214 if (len > 1 && obj->data[0] == 0) {
michael@0 215 len--;
michael@0 216 }
michael@0 217 return len;
michael@0 218 }
michael@0 219
michael@0 220 SECStatus
michael@0 221 PQG_Check(const PQGParams *params)
michael@0 222 {
michael@0 223 unsigned int L,N;
michael@0 224 SECStatus rv = SECSuccess;
michael@0 225
michael@0 226 if (params == NULL) {
michael@0 227 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 228 return SECFailure;
michael@0 229 }
michael@0 230
michael@0 231 L = PQG_GetLength(&params->prime)*PR_BITS_PER_BYTE;
michael@0 232 N = PQG_GetLength(&params->subPrime)*PR_BITS_PER_BYTE;
michael@0 233
michael@0 234 if (L < 1024) {
michael@0 235 int j;
michael@0 236
michael@0 237 /* handle DSA1 pqg parameters with less thatn 1024 bits*/
michael@0 238 if ( N != DSA1_Q_BITS ) {
michael@0 239 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 240 return SECFailure;
michael@0 241 }
michael@0 242 j = PQG_PBITS_TO_INDEX(L);
michael@0 243 if ( j < 0 ) {
michael@0 244 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 245 rv = SECFailure;
michael@0 246 }
michael@0 247 } else {
michael@0 248 /* handle DSA2 parameters (includes DSA1, 1024 bits) */
michael@0 249 rv = pqg_validate_dsa2(L, N);
michael@0 250 }
michael@0 251 return rv;
michael@0 252 }
michael@0 253
michael@0 254 HASH_HashType
michael@0 255 PQG_GetHashType(const PQGParams *params)
michael@0 256 {
michael@0 257 unsigned int L,N;
michael@0 258
michael@0 259 if (params == NULL) {
michael@0 260 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 261 return HASH_AlgNULL;
michael@0 262 }
michael@0 263
michael@0 264 L = PQG_GetLength(&params->prime)*PR_BITS_PER_BYTE;
michael@0 265 N = PQG_GetLength(&params->subPrime)*PR_BITS_PER_BYTE;
michael@0 266 return getFirstHash(L, N);
michael@0 267 }
michael@0 268
michael@0 269 /* Get a seed for generating P and Q. If in testing mode, copy in the
michael@0 270 ** seed from FIPS 186-1 appendix 5. Otherwise, obtain bytes from the
michael@0 271 ** global random number generator.
michael@0 272 */
michael@0 273 static SECStatus
michael@0 274 getPQseed(SECItem *seed, PLArenaPool* arena)
michael@0 275 {
michael@0 276 SECStatus rv;
michael@0 277
michael@0 278 if (!seed->data) {
michael@0 279 seed->data = (unsigned char*)PORT_ArenaZAlloc(arena, seed->len);
michael@0 280 }
michael@0 281 if (!seed->data) {
michael@0 282 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 283 return SECFailure;
michael@0 284 }
michael@0 285 rv = RNG_GenerateGlobalRandomBytes(seed->data, seed->len);
michael@0 286 /*
michael@0 287 * NIST CMVP disallows a sequence of 20 bytes with the most
michael@0 288 * significant byte equal to 0. Perhaps they interpret
michael@0 289 * "a sequence of at least 160 bits" as "a number >= 2^159".
michael@0 290 * So we always set the most significant bit to 1. (bug 334533)
michael@0 291 */
michael@0 292 seed->data[0] |= 0x80;
michael@0 293 return rv;
michael@0 294 }
michael@0 295
michael@0 296 /* Generate a candidate h value. If in testing mode, use the h value
michael@0 297 ** specified in FIPS 186-1 appendix 5, h = 2. Otherwise, obtain bytes
michael@0 298 ** from the global random number generator.
michael@0 299 */
michael@0 300 static SECStatus
michael@0 301 generate_h_candidate(SECItem *hit, mp_int *H)
michael@0 302 {
michael@0 303 SECStatus rv = SECSuccess;
michael@0 304 mp_err err = MP_OKAY;
michael@0 305 #ifdef FIPS_186_1_A5_TEST
michael@0 306 memset(hit->data, 0, hit->len);
michael@0 307 hit->data[hit->len-1] = 0x02;
michael@0 308 #else
michael@0 309 rv = RNG_GenerateGlobalRandomBytes(hit->data, hit->len);
michael@0 310 #endif
michael@0 311 if (rv)
michael@0 312 return SECFailure;
michael@0 313 err = mp_read_unsigned_octets(H, hit->data, hit->len);
michael@0 314 if (err) {
michael@0 315 MP_TO_SEC_ERROR(err);
michael@0 316 return SECFailure;
michael@0 317 }
michael@0 318 return SECSuccess;
michael@0 319 }
michael@0 320
michael@0 321 static SECStatus
michael@0 322 addToSeed(const SECItem * seed,
michael@0 323 unsigned long addend,
michael@0 324 int seedlen, /* g in 186-1 */
michael@0 325 SECItem * seedout)
michael@0 326 {
michael@0 327 mp_int s, sum, modulus, tmp;
michael@0 328 mp_err err = MP_OKAY;
michael@0 329 SECStatus rv = SECSuccess;
michael@0 330 MP_DIGITS(&s) = 0;
michael@0 331 MP_DIGITS(&sum) = 0;
michael@0 332 MP_DIGITS(&modulus) = 0;
michael@0 333 MP_DIGITS(&tmp) = 0;
michael@0 334 CHECK_MPI_OK( mp_init(&s) );
michael@0 335 CHECK_MPI_OK( mp_init(&sum) );
michael@0 336 CHECK_MPI_OK( mp_init(&modulus) );
michael@0 337 SECITEM_TO_MPINT(*seed, &s); /* s = seed */
michael@0 338 /* seed += addend */
michael@0 339 if (addend < MP_DIGIT_MAX) {
michael@0 340 CHECK_MPI_OK( mp_add_d(&s, (mp_digit)addend, &s) );
michael@0 341 } else {
michael@0 342 CHECK_MPI_OK( mp_init(&tmp) );
michael@0 343 CHECK_MPI_OK( mp_set_ulong(&tmp, addend) );
michael@0 344 CHECK_MPI_OK( mp_add(&s, &tmp, &s) );
michael@0 345 }
michael@0 346 /*sum = s mod 2**seedlen */
michael@0 347 CHECK_MPI_OK( mp_div_2d(&s, (mp_digit)seedlen, NULL, &sum) );
michael@0 348 if (seedout->data != NULL) {
michael@0 349 SECITEM_ZfreeItem(seedout, PR_FALSE);
michael@0 350 }
michael@0 351 MPINT_TO_SECITEM(&sum, seedout, NULL);
michael@0 352 cleanup:
michael@0 353 mp_clear(&s);
michael@0 354 mp_clear(&sum);
michael@0 355 mp_clear(&modulus);
michael@0 356 mp_clear(&tmp);
michael@0 357 if (err) {
michael@0 358 MP_TO_SEC_ERROR(err);
michael@0 359 return SECFailure;
michael@0 360 }
michael@0 361 return rv;
michael@0 362 }
michael@0 363
michael@0 364 /* Compute Hash[(SEED + addend) mod 2**g]
michael@0 365 ** Result is placed in shaOutBuf.
michael@0 366 ** This computation is used in steps 2 and 7 of FIPS 186 Appendix 2.2 and
michael@0 367 ** step 11.2 of FIPS 186-3 Appendix A.1.1.2 .
michael@0 368 */
michael@0 369 static SECStatus
michael@0 370 addToSeedThenHash(HASH_HashType hashtype,
michael@0 371 const SECItem * seed,
michael@0 372 unsigned long addend,
michael@0 373 int seedlen, /* g in 186-1 */
michael@0 374 unsigned char * hashOutBuf)
michael@0 375 {
michael@0 376 SECItem str = { 0, 0, 0 };
michael@0 377 SECStatus rv;
michael@0 378 rv = addToSeed(seed, addend, seedlen, &str);
michael@0 379 if (rv != SECSuccess) {
michael@0 380 return rv;
michael@0 381 }
michael@0 382 rv = HASH_HashBuf(hashtype, hashOutBuf, str.data, str.len);/* hash result */
michael@0 383 if (str.data)
michael@0 384 SECITEM_ZfreeItem(&str, PR_FALSE);
michael@0 385 return rv;
michael@0 386 }
michael@0 387
michael@0 388 /*
michael@0 389 ** Perform steps 2 and 3 of FIPS 186-1, appendix 2.2.
michael@0 390 ** Generate Q from seed.
michael@0 391 */
michael@0 392 static SECStatus
michael@0 393 makeQfromSeed(
michael@0 394 unsigned int g, /* input. Length of seed in bits. */
michael@0 395 const SECItem * seed, /* input. */
michael@0 396 mp_int * Q) /* output. */
michael@0 397 {
michael@0 398 unsigned char sha1[SHA1_LENGTH];
michael@0 399 unsigned char sha2[SHA1_LENGTH];
michael@0 400 unsigned char U[SHA1_LENGTH];
michael@0 401 SECStatus rv = SECSuccess;
michael@0 402 mp_err err = MP_OKAY;
michael@0 403 int i;
michael@0 404 /* ******************************************************************
michael@0 405 ** Step 2.
michael@0 406 ** "Compute U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]."
michael@0 407 **/
michael@0 408 CHECK_SEC_OK( SHA1_HashBuf(sha1, seed->data, seed->len) );
michael@0 409 CHECK_SEC_OK( addToSeedThenHash(HASH_AlgSHA1, seed, 1, g, sha2) );
michael@0 410 for (i=0; i<SHA1_LENGTH; ++i)
michael@0 411 U[i] = sha1[i] ^ sha2[i];
michael@0 412 /* ******************************************************************
michael@0 413 ** Step 3.
michael@0 414 ** "Form Q from U by setting the most signficant bit (the 2**159 bit)
michael@0 415 ** and the least signficant bit to 1. In terms of boolean operations,
michael@0 416 ** Q = U OR 2**159 OR 1. Note that 2**159 < Q < 2**160."
michael@0 417 */
michael@0 418 U[0] |= 0x80; /* U is MSB first */
michael@0 419 U[SHA1_LENGTH-1] |= 0x01;
michael@0 420 err = mp_read_unsigned_octets(Q, U, SHA1_LENGTH);
michael@0 421 cleanup:
michael@0 422 memset(U, 0, SHA1_LENGTH);
michael@0 423 memset(sha1, 0, SHA1_LENGTH);
michael@0 424 memset(sha2, 0, SHA1_LENGTH);
michael@0 425 if (err) {
michael@0 426 MP_TO_SEC_ERROR(err);
michael@0 427 return SECFailure;
michael@0 428 }
michael@0 429 return rv;
michael@0 430 }
michael@0 431
michael@0 432 /*
michael@0 433 ** Perform steps 6 and 7 of FIPS 186-3, appendix A.1.1.2.
michael@0 434 ** Generate Q from seed.
michael@0 435 */
michael@0 436 static SECStatus
michael@0 437 makeQ2fromSeed(
michael@0 438 HASH_HashType hashtype, /* selected Hashing algorithm */
michael@0 439 unsigned int N, /* input. Length of q in bits. */
michael@0 440 const SECItem * seed, /* input. */
michael@0 441 mp_int * Q) /* output. */
michael@0 442 {
michael@0 443 unsigned char U[HASH_LENGTH_MAX];
michael@0 444 SECStatus rv = SECSuccess;
michael@0 445 mp_err err = MP_OKAY;
michael@0 446 int N_bytes = N/PR_BITS_PER_BYTE; /* length of N in bytes rather than bits */
michael@0 447 int hashLen = HASH_ResultLen(hashtype);
michael@0 448 int offset = 0;
michael@0 449
michael@0 450 /* ******************************************************************
michael@0 451 ** Step 6.
michael@0 452 ** "Compute U = hash[SEED] mod 2**N-1]."
michael@0 453 **/
michael@0 454 CHECK_SEC_OK( HASH_HashBuf(hashtype, U, seed->data, seed->len) );
michael@0 455 /* mod 2**N . Step 7 will explicitly set the top bit to 1, so no need
michael@0 456 * to handle mod 2**N-1 */
michael@0 457 if (hashLen > N_bytes) {
michael@0 458 offset = hashLen - N_bytes;
michael@0 459 }
michael@0 460 /* ******************************************************************
michael@0 461 ** Step 7.
michael@0 462 ** computed_q = 2**(N-1) + U + 1 - (U mod 2)
michael@0 463 **
michael@0 464 ** This is the same as:
michael@0 465 ** computed_q = 2**(N-1) | U | 1;
michael@0 466 */
michael@0 467 U[offset] |= 0x80; /* U is MSB first */
michael@0 468 U[hashLen-1] |= 0x01;
michael@0 469 err = mp_read_unsigned_octets(Q, &U[offset], N_bytes);
michael@0 470 cleanup:
michael@0 471 memset(U, 0, HASH_LENGTH_MAX);
michael@0 472 if (err) {
michael@0 473 MP_TO_SEC_ERROR(err);
michael@0 474 return SECFailure;
michael@0 475 }
michael@0 476 return rv;
michael@0 477 }
michael@0 478
michael@0 479 /*
michael@0 480 ** Perform steps from FIPS 186-3, Appendix A.1.2.1 and Appendix C.6
michael@0 481 **
michael@0 482 ** This generates a provable prime from two smaller prime. The resulting
michael@0 483 ** prime p will have q0 as a multiple of p-1. q0 can be 1.
michael@0 484 **
michael@0 485 ** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
michael@0 486 ** steps 16 through 34 of FIPS 186-2 C.6
michael@0 487 */
michael@0 488 #define MAX_ST_SEED_BITS (HASH_LENGTH_MAX*PR_BITS_PER_BYTE)
michael@0 489 SECStatus
michael@0 490 makePrimefromPrimesShaweTaylor(
michael@0 491 HASH_HashType hashtype, /* selected Hashing algorithm */
michael@0 492 unsigned int length, /* input. Length of prime in bits. */
michael@0 493 mp_int * c0, /* seed prime */
michael@0 494 mp_int * q, /* sub prime, can be 1 */
michael@0 495 mp_int * prime, /* output. */
michael@0 496 SECItem * prime_seed, /* input/output. */
michael@0 497 int * prime_gen_counter) /* input/output. */
michael@0 498 {
michael@0 499 mp_int c;
michael@0 500 mp_int c0_2;
michael@0 501 mp_int t;
michael@0 502 mp_int a;
michael@0 503 mp_int z;
michael@0 504 mp_int two_length_minus_1;
michael@0 505 SECStatus rv = SECFailure;
michael@0 506 int hashlen = HASH_ResultLen(hashtype);
michael@0 507 int outlen = hashlen*PR_BITS_PER_BYTE;
michael@0 508 int offset;
michael@0 509 unsigned char bit, mask;
michael@0 510 /* x needs to hold roundup(L/outlen)*outlen.
michael@0 511 * This can be no larger than L+outlen-1, So we set it's size to
michael@0 512 * our max L + max outlen and know we are safe */
michael@0 513 unsigned char x[DSA_MAX_P_BITS/8+HASH_LENGTH_MAX];
michael@0 514 mp_err err = MP_OKAY;
michael@0 515 int i;
michael@0 516 int iterations;
michael@0 517 int old_counter;
michael@0 518
michael@0 519 MP_DIGITS(&c) = 0;
michael@0 520 MP_DIGITS(&c0_2) = 0;
michael@0 521 MP_DIGITS(&t) = 0;
michael@0 522 MP_DIGITS(&a) = 0;
michael@0 523 MP_DIGITS(&z) = 0;
michael@0 524 MP_DIGITS(&two_length_minus_1) = 0;
michael@0 525 CHECK_MPI_OK( mp_init(&c) );
michael@0 526 CHECK_MPI_OK( mp_init(&c0_2) );
michael@0 527 CHECK_MPI_OK( mp_init(&t) );
michael@0 528 CHECK_MPI_OK( mp_init(&a) );
michael@0 529 CHECK_MPI_OK( mp_init(&z) );
michael@0 530 CHECK_MPI_OK( mp_init(&two_length_minus_1) );
michael@0 531
michael@0 532
michael@0 533 /*
michael@0 534 ** There is a slight mapping of variable names depending on which
michael@0 535 ** FIPS 186 steps are being carried out. The mapping is as follows:
michael@0 536 ** variable A.1.2.1 C.6
michael@0 537 ** c0 p0 c0
michael@0 538 ** q q 1
michael@0 539 ** c p c
michael@0 540 ** c0_2 2*p0*q 2*c0
michael@0 541 ** length L length
michael@0 542 ** prime_seed pseed prime_seed
michael@0 543 ** prime_gen_counter pgen_counter prime_gen_counter
michael@0 544 **
michael@0 545 ** Also note: or iterations variable is actually iterations+1, since
michael@0 546 ** iterations+1 works better in C.
michael@0 547 */
michael@0 548
michael@0 549 /* Step 4/16 iterations = ceiling(length/outlen)-1 */
michael@0 550 iterations = (length+outlen-1)/outlen; /* NOTE: iterations +1 */
michael@0 551 /* Step 5/17 old_counter = prime_gen_counter */
michael@0 552 old_counter = *prime_gen_counter;
michael@0 553 /*
michael@0 554 ** Comment: Generate a pseudorandom integer x in the interval
michael@0 555 ** [2**(lenght-1), 2**length].
michael@0 556 **
michael@0 557 ** Step 6/18 x = 0
michael@0 558 */
michael@0 559 PORT_Memset(x, 0, sizeof(x));
michael@0 560 /*
michael@0 561 ** Step 7/19 for i = 0 to iterations do
michael@0 562 ** x = x + (HASH(prime_seed + i) * 2^(i*outlen))
michael@0 563 */
michael@0 564 for (i=0; i < iterations; i++) {
michael@0 565 /* is bigger than prime_seed should get to */
michael@0 566 CHECK_SEC_OK( addToSeedThenHash(hashtype, prime_seed, i,
michael@0 567 MAX_ST_SEED_BITS,&x[(iterations - i - 1)*hashlen]));
michael@0 568 }
michael@0 569 /* Step 8/20 prime_seed = prime_seed + iterations + 1 */
michael@0 570 CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
michael@0 571 prime_seed));
michael@0 572 /*
michael@0 573 ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
michael@0 574 **
michael@0 575 ** This step mathematically sets the high bit and clears out
michael@0 576 ** all the other bits higher than length. 'x' is stored
michael@0 577 ** in the x array, MSB first. The above formula gives us an 'x'
michael@0 578 ** which is length bytes long and has the high bit set. We also know
michael@0 579 ** that length <= iterations*outlen since
michael@0 580 ** iterations=ceiling(length/outlen). First we find the offset in
michael@0 581 ** bytes into the array where the high bit is.
michael@0 582 */
michael@0 583 offset = (outlen*iterations - length)/PR_BITS_PER_BYTE;
michael@0 584 /* now we want to set the 'high bit', since length may not be a
michael@0 585 * multiple of 8,*/
michael@0 586 bit = 1 << ((length-1) & 0x7); /* select the proper bit in the byte */
michael@0 587 /* we need to zero out the rest of the bits in the byte above */
michael@0 588 mask = (bit-1);
michael@0 589 /* now we set it */
michael@0 590 x[offset] = (mask & x[offset]) | bit;
michael@0 591 /*
michael@0 592 ** Comment: Generate a candidate prime c in the interval
michael@0 593 ** [2**(lenght-1), 2**length].
michael@0 594 **
michael@0 595 ** Step 10 t = ceiling(x/(2q(p0)))
michael@0 596 ** Step 22 t = ceiling(x/(2(c0)))
michael@0 597 */
michael@0 598 CHECK_MPI_OK( mp_read_unsigned_octets(&t, &x[offset],
michael@0 599 hashlen*iterations - offset ) ); /* t = x */
michael@0 600 CHECK_MPI_OK( mp_mul(c0, q, &c0_2) ); /* c0_2 is now c0*q */
michael@0 601 CHECK_MPI_OK( mp_add(&c0_2, &c0_2, &c0_2) ); /* c0_2 is now 2*q*c0 */
michael@0 602 CHECK_MPI_OK( mp_add(&t, &c0_2, &t) ); /* t = x+2*q*c0 */
michael@0 603 CHECK_MPI_OK( mp_sub_d(&t, (mp_digit) 1, &t) ); /* t = x+2*q*c0 -1 */
michael@0 604 /* t = floor((x+2qc0-1)/2qc0) = ceil(x/2qc0) */
michael@0 605 CHECK_MPI_OK( mp_div(&t, &c0_2, &t, NULL) );
michael@0 606 /*
michael@0 607 ** step 11: if (2tqp0 +1 > 2**length), then t = ceiling(2**(length-1)/2qp0)
michael@0 608 ** step 12: t = 2tqp0 +1.
michael@0 609 **
michael@0 610 ** step 23: if (2tc0 +1 > 2**length), then t = ceiling(2**(length-1)/2c0)
michael@0 611 ** step 24: t = 2tc0 +1.
michael@0 612 */
michael@0 613 CHECK_MPI_OK( mp_2expt(&two_length_minus_1, length-1) );
michael@0 614 step_23:
michael@0 615 CHECK_MPI_OK( mp_mul(&t, &c0_2, &c) ); /* c = t*2qc0 */
michael@0 616 CHECK_MPI_OK( mp_add_d(&c, (mp_digit)1, &c) ); /* c= 2tqc0 + 1*/
michael@0 617 if (mpl_significant_bits(&c) > length) { /* if c > 2**length */
michael@0 618 CHECK_MPI_OK( mp_sub_d(&c0_2, (mp_digit) 1, &t) ); /* t = 2qc0-1 */
michael@0 619 /* t = 2**(length-1) + 2qc0 -1 */
michael@0 620 CHECK_MPI_OK( mp_add(&two_length_minus_1,&t, &t) );
michael@0 621 /* t = floor((2**(length-1)+2qc0 -1)/2qco)
michael@0 622 * = ceil(2**(lenght-2)/2qc0) */
michael@0 623 CHECK_MPI_OK( mp_div(&t, &c0_2, &t, NULL) );
michael@0 624 CHECK_MPI_OK( mp_mul(&t, &c0_2, &c) );
michael@0 625 CHECK_MPI_OK( mp_add_d(&c, (mp_digit)1, &c) ); /* c= 2tqc0 + 1*/
michael@0 626 }
michael@0 627 /* Step 13/25 prime_gen_counter = prime_gen_counter + 1*/
michael@0 628 (*prime_gen_counter)++;
michael@0 629 /*
michael@0 630 ** Comment: Test the candidate prime c for primality; first pick an
michael@0 631 ** integer a between 2 and c-2.
michael@0 632 **
michael@0 633 ** Step 14/26 a=0
michael@0 634 */
michael@0 635 PORT_Memset(x, 0, sizeof(x)); /* use x for a */
michael@0 636 /*
michael@0 637 ** Step 15/27 for i = 0 to iterations do
michael@0 638 ** a = a + (HASH(prime_seed + i) * 2^(i*outlen))
michael@0 639 **
michael@0 640 ** NOTE: we reuse the x array for 'a' initially.
michael@0 641 */
michael@0 642 for (i=0; i < iterations; i++) {
michael@0 643 /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
michael@0 644 CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
michael@0 645 MAX_ST_SEED_BITS,&x[(iterations - i - 1)*hashlen]));
michael@0 646 }
michael@0 647 /* Step 16/28 prime_seed = prime_seed + iterations + 1 */
michael@0 648 CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
michael@0 649 prime_seed));
michael@0 650 /* Step 17/29 a = 2 + (a mod (c-3)). */
michael@0 651 CHECK_MPI_OK( mp_read_unsigned_octets(&a, x, iterations*hashlen) );
michael@0 652 CHECK_MPI_OK( mp_sub_d(&c, (mp_digit) 3, &z) ); /* z = c -3 */
michael@0 653 CHECK_MPI_OK( mp_mod(&a, &z, &a) ); /* a = a mod c -3 */
michael@0 654 CHECK_MPI_OK( mp_add_d(&a, (mp_digit) 2, &a) ); /* a = 2 + a mod c -3 */
michael@0 655 /*
michael@0 656 ** Step 18 z = a**(2tq) mod p.
michael@0 657 ** Step 30 z = a**(2t) mod c.
michael@0 658 */
michael@0 659 CHECK_MPI_OK( mp_mul(&t, q, &z) ); /* z = tq */
michael@0 660 CHECK_MPI_OK( mp_add(&z, &z, &z) ); /* z = 2tq */
michael@0 661 CHECK_MPI_OK( mp_exptmod(&a, &z, &c, &z) ); /* z = a**(2tq) mod c */
michael@0 662 /*
michael@0 663 ** Step 19 if (( 1 == GCD(z-1,p)) and ( 1 == z**p0 mod p )), then
michael@0 664 ** Step 31 if (( 1 == GCD(z-1,c)) and ( 1 == z**c0 mod c )), then
michael@0 665 */
michael@0 666 CHECK_MPI_OK( mp_sub_d(&z, (mp_digit) 1, &a) );
michael@0 667 CHECK_MPI_OK( mp_gcd(&a,&c,&a ));
michael@0 668 if (mp_cmp_d(&a, (mp_digit)1) == 0) {
michael@0 669 CHECK_MPI_OK( mp_exptmod(&z, c0, &c, &a) );
michael@0 670 if (mp_cmp_d(&a, (mp_digit)1) == 0) {
michael@0 671 /* Step 31.1 prime = c */
michael@0 672 CHECK_MPI_OK( mp_copy(&c, prime) );
michael@0 673 /*
michael@0 674 ** Step 31.2 return Success, prime, prime_seed,
michael@0 675 ** prime_gen_counter
michael@0 676 */
michael@0 677 rv = SECSuccess;
michael@0 678 goto cleanup;
michael@0 679 }
michael@0 680 }
michael@0 681 /*
michael@0 682 ** Step 20/32 If (prime_gen_counter > 4 * length + old_counter then
michael@0 683 ** return (FAILURE, 0, 0, 0).
michael@0 684 ** NOTE: the test is reversed, so we fall through on failure to the
michael@0 685 ** cleanup routine
michael@0 686 */
michael@0 687 if (*prime_gen_counter < (4*length + old_counter)) {
michael@0 688 /* Step 21/33 t = t + 1 */
michael@0 689 CHECK_MPI_OK( mp_add_d(&t, (mp_digit) 1, &t) );
michael@0 690 /* Step 22/34 Go to step 23/11 */
michael@0 691 goto step_23;
michael@0 692 }
michael@0 693
michael@0 694 /* if (prime_gencont > (4*length + old_counter), fall through to failure */
michael@0 695 rv = SECFailure; /* really is already set, but paranoia is good */
michael@0 696
michael@0 697 cleanup:
michael@0 698 mp_clear(&c);
michael@0 699 mp_clear(&c0_2);
michael@0 700 mp_clear(&t);
michael@0 701 mp_clear(&a);
michael@0 702 mp_clear(&z);
michael@0 703 mp_clear(&two_length_minus_1);
michael@0 704 if (err) {
michael@0 705 MP_TO_SEC_ERROR(err);
michael@0 706 rv = SECFailure;
michael@0 707 }
michael@0 708 if (rv == SECFailure) {
michael@0 709 mp_zero(prime);
michael@0 710 if (prime_seed->data) {
michael@0 711 SECITEM_FreeItem(prime_seed, PR_FALSE);
michael@0 712 }
michael@0 713 *prime_gen_counter = 0;
michael@0 714 }
michael@0 715 return rv;
michael@0 716 }
michael@0 717
michael@0 718 /*
michael@0 719 ** Perform steps from FIPS 186-3, Appendix C.6
michael@0 720 **
michael@0 721 ** This generates a provable prime from a seed
michael@0 722 */
michael@0 723 SECStatus
michael@0 724 makePrimefromSeedShaweTaylor(
michael@0 725 HASH_HashType hashtype, /* selected Hashing algorithm */
michael@0 726 unsigned int length, /* input. Length of prime in bits. */
michael@0 727 const SECItem * input_seed, /* input. */
michael@0 728 mp_int * prime, /* output. */
michael@0 729 SECItem * prime_seed, /* output. */
michael@0 730 int * prime_gen_counter) /* output. */
michael@0 731 {
michael@0 732 mp_int c;
michael@0 733 mp_int c0;
michael@0 734 mp_int one;
michael@0 735 SECStatus rv = SECFailure;
michael@0 736 int hashlen = HASH_ResultLen(hashtype);
michael@0 737 int outlen = hashlen*PR_BITS_PER_BYTE;
michael@0 738 int offset;
michael@0 739 unsigned char bit, mask;
michael@0 740 unsigned char x[HASH_LENGTH_MAX*2];
michael@0 741 mp_digit dummy;
michael@0 742 mp_err err = MP_OKAY;
michael@0 743 int i;
michael@0 744
michael@0 745 MP_DIGITS(&c) = 0;
michael@0 746 MP_DIGITS(&c0) = 0;
michael@0 747 MP_DIGITS(&one) = 0;
michael@0 748 CHECK_MPI_OK( mp_init(&c) );
michael@0 749 CHECK_MPI_OK( mp_init(&c0) );
michael@0 750 CHECK_MPI_OK( mp_init(&one) );
michael@0 751
michael@0 752 /* Step 1. if length < 2 then return (FAILURE, 0, 0, 0) */
michael@0 753 if (length < 2) {
michael@0 754 rv = SECFailure;
michael@0 755 goto cleanup;
michael@0 756 }
michael@0 757 /* Step 2. if length >= 33 then goto step 14 */
michael@0 758 if (length >= 33) {
michael@0 759 mp_zero(&one);
michael@0 760 CHECK_MPI_OK( mp_add_d(&one, (mp_digit) 1, &one) );
michael@0 761
michael@0 762 /* Step 14 (status, c0, prime_seed, prime_gen_counter) =
michael@0 763 ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
michael@0 764 */
michael@0 765 rv = makePrimefromSeedShaweTaylor(hashtype, (length+1)/2+1,
michael@0 766 input_seed, &c0, prime_seed, prime_gen_counter);
michael@0 767 /* Step 15 if FAILURE is returned, return (FAILURE, 0, 0, 0). */
michael@0 768 if (rv != SECSuccess) {
michael@0 769 goto cleanup;
michael@0 770 }
michael@0 771 /* Steps 16-34 */
michael@0 772 rv = makePrimefromPrimesShaweTaylor(hashtype,length, &c0, &one,
michael@0 773 prime, prime_seed, prime_gen_counter);
michael@0 774 goto cleanup; /* we're done, one way or the other */
michael@0 775 }
michael@0 776 /* Step 3 prime_seed = input_seed */
michael@0 777 CHECK_SEC_OK(SECITEM_CopyItem(NULL, prime_seed, input_seed));
michael@0 778 /* Step 4 prime_gen_count = 0 */
michael@0 779 *prime_gen_counter = 0;
michael@0 780
michael@0 781 step_5:
michael@0 782 /* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
michael@0 783 CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len) );
michael@0 784 CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
michael@0 785 MAX_ST_SEED_BITS, &x[hashlen]) );
michael@0 786 for (i=0; i < hashlen; i++) {
michael@0 787 x[i] = x[i] ^ x[i+hashlen];
michael@0 788 }
michael@0 789 /* Step 6 c = 2**length-1 + c mod 2**length-1 */
michael@0 790 /* This step mathematically sets the high bit and clears out
michael@0 791 ** all the other bits higher than length. Right now c is stored
michael@0 792 ** in the x array, MSB first. The above formula gives us a c which
michael@0 793 ** is length bytes long and has the high bit set. We also know that
michael@0 794 ** length < outlen since the smallest outlen is 160 bits and the largest
michael@0 795 ** length at this point is 32 bits. So first we find the offset in bytes
michael@0 796 ** into the array where the high bit is.
michael@0 797 */
michael@0 798 offset = (outlen - length)/PR_BITS_PER_BYTE;
michael@0 799 /* now we want to set the 'high bit'. We have to calculate this since
michael@0 800 * length may not be a multiple of 8.*/
michael@0 801 bit = 1 << ((length-1) & 0x7); /* select the proper bit in the byte */
michael@0 802 /* we need to zero out the rest of the bits in the byte above */
michael@0 803 mask = (bit-1);
michael@0 804 /* now we set it */
michael@0 805 x[offset] = (mask & x[offset]) | bit;
michael@0 806 /* Step 7 c = c*floor(c/2) + 1 */
michael@0 807 /* set the low bit. much easier to find (the end of the array) */
michael@0 808 x[hashlen-1] |= 1;
michael@0 809 /* now that we've set our bits, we can create our candidate "c" */
michael@0 810 CHECK_MPI_OK( mp_read_unsigned_octets(&c, &x[offset], hashlen-offset) );
michael@0 811 /* Step 8 prime_gen_counter = prime_gen_counter + 1 */
michael@0 812 (*prime_gen_counter)++;
michael@0 813 /* Step 9 prime_seed = prime_seed + 2 */
michael@0 814 CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
michael@0 815 /* Step 10 Perform deterministic primality test on c. For example, since
michael@0 816 ** c is small, it's primality can be tested by trial division, See
michael@0 817 ** See Appendic C.7.
michael@0 818 **
michael@0 819 ** We in fact test with trial division. mpi has a built int trial divider
michael@0 820 ** that divides all divisors up to 2^16.
michael@0 821 */
michael@0 822 if (prime_tab[prime_tab_size-1] < 0xFFF1) {
michael@0 823 /* we aren't testing all the primes between 0 and 2^16, we really
michael@0 824 * can't use this construction. Just fail. */
michael@0 825 rv = SECFailure;
michael@0 826 goto cleanup;
michael@0 827 }
michael@0 828 dummy = prime_tab_size;
michael@0 829 err = mpp_divis_primes(&c, &dummy);
michael@0 830 /* Step 11 if c is prime then */
michael@0 831 if (err == MP_NO) {
michael@0 832 /* Step 11.1 prime = c */
michael@0 833 CHECK_MPI_OK( mp_copy(&c, prime) );
michael@0 834 /* Step 11.2 return SUCCESS prime, prime_seed, prime_gen_counter */
michael@0 835 err = MP_OKAY;
michael@0 836 rv = SECSuccess;
michael@0 837 goto cleanup;
michael@0 838 } else if (err != MP_YES) {
michael@0 839 goto cleanup; /* function failed, bail out */
michael@0 840 } else {
michael@0 841 /* reset mp_err */
michael@0 842 err = MP_OKAY;
michael@0 843 }
michael@0 844 /*
michael@0 845 ** Step 12 if (prime_gen_counter > (4*len))
michael@0 846 ** then return (FAILURE, 0, 0, 0))
michael@0 847 ** Step 13 goto step 5
michael@0 848 */
michael@0 849 if (*prime_gen_counter <= (4*length)) {
michael@0 850 goto step_5;
michael@0 851 }
michael@0 852 /* if (prime_gencont > 4*length), fall through to failure */
michael@0 853 rv = SECFailure; /* really is already set, but paranoia is good */
michael@0 854
michael@0 855 cleanup:
michael@0 856 mp_clear(&c);
michael@0 857 mp_clear(&c0);
michael@0 858 mp_clear(&one);
michael@0 859 if (err) {
michael@0 860 MP_TO_SEC_ERROR(err);
michael@0 861 rv = SECFailure;
michael@0 862 }
michael@0 863 if (rv == SECFailure) {
michael@0 864 mp_zero(prime);
michael@0 865 if (prime_seed->data) {
michael@0 866 SECITEM_FreeItem(prime_seed, PR_FALSE);
michael@0 867 }
michael@0 868 *prime_gen_counter = 0;
michael@0 869 }
michael@0 870 return rv;
michael@0 871 }
michael@0 872
michael@0 873
michael@0 874 /*
michael@0 875 * Find a Q and algorithm from Seed.
michael@0 876 */
michael@0 877 static SECStatus
michael@0 878 findQfromSeed(
michael@0 879 unsigned int L, /* input. Length of p in bits. */
michael@0 880 unsigned int N, /* input. Length of q in bits. */
michael@0 881 unsigned int g, /* input. Length of seed in bits. */
michael@0 882 const SECItem * seed, /* input. */
michael@0 883 mp_int * Q, /* input. */
michael@0 884 mp_int * Q_, /* output. */
michael@0 885 int * qseed_len, /* output */
michael@0 886 HASH_HashType *hashtypePtr, /* output. Hash uses */
michael@0 887 pqgGenType *typePtr) /* output. Generation Type used */
michael@0 888 {
michael@0 889 HASH_HashType hashtype;
michael@0 890 SECItem firstseed = { 0, 0, 0 };
michael@0 891 SECItem qseed = { 0, 0, 0 };
michael@0 892 SECStatus rv;
michael@0 893
michael@0 894 *qseed_len = 0; /* only set if FIPS186_3_ST_TYPE */
michael@0 895
michael@0 896 /* handle legacy small DSA first can only be FIPS186_1_TYPE */
michael@0 897 if (L < 1024) {
michael@0 898 rv =makeQfromSeed(g,seed,Q_);
michael@0 899 if ((rv == SECSuccess) && (mp_cmp(Q,Q_) == 0)) {
michael@0 900 *hashtypePtr = HASH_AlgSHA1;
michael@0 901 *typePtr = FIPS186_1_TYPE;
michael@0 902 return SECSuccess;
michael@0 903 }
michael@0 904 return SECFailure;
michael@0 905 }
michael@0 906 /* 1024 could use FIPS186_1 or FIPS186_3 algorithms, we need to try
michael@0 907 * them both */
michael@0 908 if (L == 1024) {
michael@0 909 rv = makeQfromSeed(g,seed,Q_);
michael@0 910 if (rv == SECSuccess) {
michael@0 911 if (mp_cmp(Q,Q_) == 0) {
michael@0 912 *hashtypePtr = HASH_AlgSHA1;
michael@0 913 *typePtr = FIPS186_1_TYPE;
michael@0 914 return SECSuccess;
michael@0 915 }
michael@0 916 }
michael@0 917 /* fall through for FIPS186_3 types */
michael@0 918 }
michael@0 919 /* at this point we know we aren't using FIPS186_1, start trying FIPS186_3
michael@0 920 * with appropriate hash types */
michael@0 921 for (hashtype = getFirstHash(L,N); hashtype != HASH_AlgTOTAL;
michael@0 922 hashtype=getNextHash(hashtype)) {
michael@0 923 rv = makeQ2fromSeed(hashtype, N, seed, Q_);
michael@0 924 if (rv != SECSuccess) {
michael@0 925 continue;
michael@0 926 }
michael@0 927 if (mp_cmp(Q,Q_) == 0) {
michael@0 928 *hashtypePtr = hashtype;
michael@0 929 *typePtr = FIPS186_3_TYPE;
michael@0 930 return SECSuccess;
michael@0 931 }
michael@0 932 }
michael@0 933 /*
michael@0 934 * OK finally try FIPS186_3 Shawe-Taylor
michael@0 935 */
michael@0 936 firstseed = *seed;
michael@0 937 firstseed.len = seed->len/3;
michael@0 938 for (hashtype = getFirstHash(L,N); hashtype != HASH_AlgTOTAL;
michael@0 939 hashtype=getNextHash(hashtype)) {
michael@0 940 int count;
michael@0 941
michael@0 942 rv = makePrimefromSeedShaweTaylor(hashtype, N, &firstseed, Q_,
michael@0 943 &qseed, &count);
michael@0 944 if (rv != SECSuccess) {
michael@0 945 continue;
michael@0 946 }
michael@0 947 if (mp_cmp(Q,Q_) == 0) {
michael@0 948 /* check qseed as well... */
michael@0 949 int offset = seed->len - qseed.len;
michael@0 950 if ((offset < 0) ||
michael@0 951 (PORT_Memcmp(&seed->data[offset],qseed.data,qseed.len) != 0)) {
michael@0 952 /* we found q, but the seeds don't match. This isn't an
michael@0 953 * accident, someone has been tweeking with the seeds, just
michael@0 954 * fail a this point. */
michael@0 955 SECITEM_FreeItem(&qseed,PR_FALSE);
michael@0 956 return SECFailure;
michael@0 957 }
michael@0 958 *qseed_len = qseed.len;
michael@0 959 *hashtypePtr = hashtype;
michael@0 960 *typePtr = FIPS186_3_ST_TYPE;
michael@0 961 SECITEM_FreeItem(&qseed, PR_FALSE);
michael@0 962 return SECSuccess;
michael@0 963 }
michael@0 964 SECITEM_FreeItem(&qseed, PR_FALSE);
michael@0 965 }
michael@0 966 /* no hash algorithms found which match seed to Q, fail */
michael@0 967 return SECFailure;
michael@0 968 }
michael@0 969
michael@0 970
michael@0 971
michael@0 972 /*
michael@0 973 ** Perform steps 7, 8 and 9 of FIPS 186, appendix 2.2.
michael@0 974 ** which are the same as steps 11.1-11.5 of FIPS 186-2, App A.1.1.2
michael@0 975 ** Generate P from Q, seed, L, and offset.
michael@0 976 */
michael@0 977 static SECStatus
michael@0 978 makePfromQandSeed(
michael@0 979 HASH_HashType hashtype, /* selected Hashing algorithm */
michael@0 980 unsigned int L, /* Length of P in bits. Per FIPS 186. */
michael@0 981 unsigned int N, /* Length of Q in bits. Per FIPS 186. */
michael@0 982 unsigned int offset, /* Per FIPS 186, App 2.2. & 186-3 App A.1.1.2 */
michael@0 983 unsigned int seedlen, /* input. Length of seed in bits. (g in 186-1)*/
michael@0 984 const SECItem * seed, /* input. */
michael@0 985 const mp_int * Q, /* input. */
michael@0 986 mp_int * P) /* output. */
michael@0 987 {
michael@0 988 unsigned int j; /* Per FIPS 186-3 App. A.1.1.2 (k in 186-1)*/
michael@0 989 unsigned int n; /* Per FIPS 186, appendix 2.2. */
michael@0 990 mp_digit b; /* Per FIPS 186, appendix 2.2. */
michael@0 991 unsigned int outlen; /* Per FIPS 186-3 App. A.1.1.2 */
michael@0 992 unsigned int hashlen; /* outlen in bytes */
michael@0 993 unsigned char V_j[HASH_LENGTH_MAX];
michael@0 994 mp_int W, X, c, twoQ, V_n, tmp;
michael@0 995 mp_err err = MP_OKAY;
michael@0 996 SECStatus rv = SECSuccess;
michael@0 997 /* Initialize bignums */
michael@0 998 MP_DIGITS(&W) = 0;
michael@0 999 MP_DIGITS(&X) = 0;
michael@0 1000 MP_DIGITS(&c) = 0;
michael@0 1001 MP_DIGITS(&twoQ) = 0;
michael@0 1002 MP_DIGITS(&V_n) = 0;
michael@0 1003 MP_DIGITS(&tmp) = 0;
michael@0 1004 CHECK_MPI_OK( mp_init(&W) );
michael@0 1005 CHECK_MPI_OK( mp_init(&X) );
michael@0 1006 CHECK_MPI_OK( mp_init(&c) );
michael@0 1007 CHECK_MPI_OK( mp_init(&twoQ) );
michael@0 1008 CHECK_MPI_OK( mp_init(&tmp) );
michael@0 1009 CHECK_MPI_OK( mp_init(&V_n) );
michael@0 1010
michael@0 1011 hashlen = HASH_ResultLen(hashtype);
michael@0 1012 outlen = hashlen*PR_BITS_PER_BYTE;
michael@0 1013
michael@0 1014 /* L - 1 = n*outlen + b */
michael@0 1015 n = (L - 1) / outlen;
michael@0 1016 b = (L - 1) % outlen;
michael@0 1017
michael@0 1018 /* ******************************************************************
michael@0 1019 ** Step 11.1 (Step 7 in 186-1)
michael@0 1020 ** "for j = 0 ... n let
michael@0 1021 ** V_j = SHA[(SEED + offset + j) mod 2**seedlen]."
michael@0 1022 **
michael@0 1023 ** Step 11.2 (Step 8 in 186-1)
michael@0 1024 ** "W = V_0 + (V_1 * 2**outlen) + ... + (V_n-1 * 2**((n-1)*outlen))
michael@0 1025 ** + ((V_n mod 2**b) * 2**(n*outlen))
michael@0 1026 */
michael@0 1027 for (j=0; j<n; ++j) { /* Do the first n terms of V_j */
michael@0 1028 /* Do step 11.1 for iteration j.
michael@0 1029 ** V_j = HASH[(seed + offset + j) mod 2**g]
michael@0 1030 */
michael@0 1031 CHECK_SEC_OK( addToSeedThenHash(hashtype,seed,offset+j, seedlen, V_j) );
michael@0 1032 /* Do step 11.2 for iteration j.
michael@0 1033 ** W += V_j * 2**(j*outlen)
michael@0 1034 */
michael@0 1035 OCTETS_TO_MPINT(V_j, &tmp, hashlen); /* get bignum V_j */
michael@0 1036 CHECK_MPI_OK( mpl_lsh(&tmp, &tmp, j*outlen) );/* tmp=V_j << j*outlen */
michael@0 1037 CHECK_MPI_OK( mp_add(&W, &tmp, &W) ); /* W += tmp */
michael@0 1038 }
michael@0 1039 /* Step 11.2, continued.
michael@0 1040 ** [W += ((V_n mod 2**b) * 2**(n*outlen))]
michael@0 1041 */
michael@0 1042 CHECK_SEC_OK( addToSeedThenHash(hashtype, seed, offset + n, seedlen, V_j) );
michael@0 1043 OCTETS_TO_MPINT(V_j, &V_n, hashlen); /* get bignum V_n */
michael@0 1044 CHECK_MPI_OK( mp_div_2d(&V_n, b, NULL, &tmp) ); /* tmp = V_n mod 2**b */
michael@0 1045 CHECK_MPI_OK( mpl_lsh(&tmp, &tmp, n*outlen) ); /* tmp = tmp << n*outlen */
michael@0 1046 CHECK_MPI_OK( mp_add(&W, &tmp, &W) ); /* W += tmp */
michael@0 1047 /* Step 11.3, (Step 8 in 186-1)
michael@0 1048 ** "X = W + 2**(L-1).
michael@0 1049 ** Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L."
michael@0 1050 */
michael@0 1051 CHECK_MPI_OK( mpl_set_bit(&X, (mp_size)(L-1), 1) ); /* X = 2**(L-1) */
michael@0 1052 CHECK_MPI_OK( mp_add(&X, &W, &X) ); /* X += W */
michael@0 1053 /*************************************************************
michael@0 1054 ** Step 11.4. (Step 9 in 186-1)
michael@0 1055 ** "c = X mod 2q"
michael@0 1056 */
michael@0 1057 CHECK_MPI_OK( mp_mul_2(Q, &twoQ) ); /* 2q */
michael@0 1058 CHECK_MPI_OK( mp_mod(&X, &twoQ, &c) ); /* c = X mod 2q */
michael@0 1059 /*************************************************************
michael@0 1060 ** Step 11.5. (Step 9 in 186-1)
michael@0 1061 ** "p = X - (c - 1).
michael@0 1062 ** Note that p is congruent to 1 mod 2q."
michael@0 1063 */
michael@0 1064 CHECK_MPI_OK( mp_sub_d(&c, 1, &c) ); /* c -= 1 */
michael@0 1065 CHECK_MPI_OK( mp_sub(&X, &c, P) ); /* P = X - c */
michael@0 1066 cleanup:
michael@0 1067 mp_clear(&W);
michael@0 1068 mp_clear(&X);
michael@0 1069 mp_clear(&c);
michael@0 1070 mp_clear(&twoQ);
michael@0 1071 mp_clear(&V_n);
michael@0 1072 mp_clear(&tmp);
michael@0 1073 if (err) {
michael@0 1074 MP_TO_SEC_ERROR(err);
michael@0 1075 return SECFailure;
michael@0 1076 }
michael@0 1077 return rv;
michael@0 1078 }
michael@0 1079
michael@0 1080 /*
michael@0 1081 ** Generate G from h, P, and Q.
michael@0 1082 */
michael@0 1083 static SECStatus
michael@0 1084 makeGfromH(const mp_int *P, /* input. */
michael@0 1085 const mp_int *Q, /* input. */
michael@0 1086 mp_int *H, /* input and output. */
michael@0 1087 mp_int *G, /* output. */
michael@0 1088 PRBool *passed)
michael@0 1089 {
michael@0 1090 mp_int exp, pm1;
michael@0 1091 mp_err err = MP_OKAY;
michael@0 1092 SECStatus rv = SECSuccess;
michael@0 1093 *passed = PR_FALSE;
michael@0 1094 MP_DIGITS(&exp) = 0;
michael@0 1095 MP_DIGITS(&pm1) = 0;
michael@0 1096 CHECK_MPI_OK( mp_init(&exp) );
michael@0 1097 CHECK_MPI_OK( mp_init(&pm1) );
michael@0 1098 CHECK_MPI_OK( mp_sub_d(P, 1, &pm1) ); /* P - 1 */
michael@0 1099 if ( mp_cmp(H, &pm1) >= 0) /* H >= P-1 */
michael@0 1100 CHECK_MPI_OK( mp_sub(H, &pm1, H) ); /* H = H mod (P-1) */
michael@0 1101 /* Let b = 2**n (smallest power of 2 greater than P).
michael@0 1102 ** Since P-1 >= b/2, and H < b, quotient(H/(P-1)) = 0 or 1
michael@0 1103 ** so the above operation safely computes H mod (P-1)
michael@0 1104 */
michael@0 1105 /* Check for H = to 0 or 1. Regen H if so. (Regen means return error). */
michael@0 1106 if (mp_cmp_d(H, 1) <= 0) {
michael@0 1107 rv = SECFailure;
michael@0 1108 goto cleanup;
michael@0 1109 }
michael@0 1110 /* Compute G, according to the equation G = (H ** ((P-1)/Q)) mod P */
michael@0 1111 CHECK_MPI_OK( mp_div(&pm1, Q, &exp, NULL) ); /* exp = (P-1)/Q */
michael@0 1112 CHECK_MPI_OK( mp_exptmod(H, &exp, P, G) ); /* G = H ** exp mod P */
michael@0 1113 /* Check for G == 0 or G == 1, return error if so. */
michael@0 1114 if (mp_cmp_d(G, 1) <= 0) {
michael@0 1115 rv = SECFailure;
michael@0 1116 goto cleanup;
michael@0 1117 }
michael@0 1118 *passed = PR_TRUE;
michael@0 1119 cleanup:
michael@0 1120 mp_clear(&exp);
michael@0 1121 mp_clear(&pm1);
michael@0 1122 if (err) {
michael@0 1123 MP_TO_SEC_ERROR(err);
michael@0 1124 rv = SECFailure;
michael@0 1125 }
michael@0 1126 return rv;
michael@0 1127 }
michael@0 1128
michael@0 1129 /*
michael@0 1130 ** Generate G from seed, index, P, and Q.
michael@0 1131 */
michael@0 1132 static SECStatus
michael@0 1133 makeGfromIndex(HASH_HashType hashtype,
michael@0 1134 const mp_int *P, /* input. */
michael@0 1135 const mp_int *Q, /* input. */
michael@0 1136 const SECItem *seed, /* input. */
michael@0 1137 unsigned char index, /* input. */
michael@0 1138 mp_int *G) /* input/output */
michael@0 1139 {
michael@0 1140 mp_int e, pm1, W;
michael@0 1141 unsigned int count;
michael@0 1142 unsigned char data[HASH_LENGTH_MAX];
michael@0 1143 unsigned int len;
michael@0 1144 mp_err err = MP_OKAY;
michael@0 1145 SECStatus rv = SECSuccess;
michael@0 1146 const SECHashObject *hashobj;
michael@0 1147 void *hashcx = NULL;
michael@0 1148
michael@0 1149 MP_DIGITS(&e) = 0;
michael@0 1150 MP_DIGITS(&pm1) = 0;
michael@0 1151 MP_DIGITS(&W) = 0;
michael@0 1152 CHECK_MPI_OK( mp_init(&e) );
michael@0 1153 CHECK_MPI_OK( mp_init(&pm1) );
michael@0 1154 CHECK_MPI_OK( mp_init(&W) );
michael@0 1155
michael@0 1156 /* initialize our hash stuff */
michael@0 1157 hashobj = HASH_GetRawHashObject(hashtype);
michael@0 1158 if (hashobj == NULL) {
michael@0 1159 /* shouldn't happen */
michael@0 1160 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
michael@0 1161 rv = SECFailure;
michael@0 1162 goto cleanup;
michael@0 1163 }
michael@0 1164 hashcx = hashobj->create();
michael@0 1165 if (hashcx == NULL) {
michael@0 1166 rv = SECFailure;
michael@0 1167 goto cleanup;
michael@0 1168 }
michael@0 1169
michael@0 1170 CHECK_MPI_OK( mp_sub_d(P, 1, &pm1) ); /* P - 1 */
michael@0 1171 /* Step 3 e = (p-1)/q */
michael@0 1172 CHECK_MPI_OK( mp_div(&pm1, Q, &e, NULL) ); /* e = (P-1)/Q */
michael@0 1173 /* Steps 4, 5, and 6 */
michael@0 1174 /* count is a 16 bit value in the spec. We actually represent count
michael@0 1175 * as more than 16 bits so we can easily detect the 16 bit overflow */
michael@0 1176 #define MAX_COUNT 0x10000
michael@0 1177 for (count = 1; count < MAX_COUNT; count++) {
michael@0 1178 /* step 7
michael@0 1179 * U = domain_param_seed || "ggen" || index || count
michael@0 1180 * step 8
michael@0 1181 * W = HASH(U)
michael@0 1182 */
michael@0 1183 hashobj->begin(hashcx);
michael@0 1184 hashobj->update(hashcx,seed->data,seed->len);
michael@0 1185 hashobj->update(hashcx, (unsigned char *)"ggen", 4);
michael@0 1186 hashobj->update(hashcx,&index, 1);
michael@0 1187 data[0] = (count >> 8) & 0xff;
michael@0 1188 data[1] = count & 0xff;
michael@0 1189 hashobj->update(hashcx, data, 2);
michael@0 1190 hashobj->end(hashcx, data, &len, sizeof(data));
michael@0 1191 OCTETS_TO_MPINT(data, &W, len);
michael@0 1192 /* step 9. g = W**e mod p */
michael@0 1193 CHECK_MPI_OK( mp_exptmod(&W, &e, P, G) );
michael@0 1194 /* step 10. if (g < 2) then goto step 5 */
michael@0 1195 /* NOTE: this weird construct is to keep the flow according to the spec.
michael@0 1196 * the continue puts us back to step 5 of the for loop */
michael@0 1197 if (mp_cmp_d(G, 2) < 0) {
michael@0 1198 continue;
michael@0 1199 }
michael@0 1200 break; /* step 11 follows step 10 if the test condition is false */
michael@0 1201 }
michael@0 1202 if (count >= MAX_COUNT) {
michael@0 1203 rv = SECFailure; /* last part of step 6 */
michael@0 1204 }
michael@0 1205 /* step 11.
michael@0 1206 * return valid G */
michael@0 1207 cleanup:
michael@0 1208 PORT_Memset(data, 0, sizeof(data));
michael@0 1209 if (hashcx) {
michael@0 1210 hashobj->destroy(hashcx, PR_TRUE);
michael@0 1211 }
michael@0 1212 mp_clear(&e);
michael@0 1213 mp_clear(&pm1);
michael@0 1214 mp_clear(&W);
michael@0 1215 if (err) {
michael@0 1216 MP_TO_SEC_ERROR(err);
michael@0 1217 rv = SECFailure;
michael@0 1218 }
michael@0 1219 return rv;
michael@0 1220 }
michael@0 1221
michael@0 1222 /* This code uses labels and gotos, so that it can follow the numbered
michael@0 1223 ** steps in the algorithms from FIPS 186-3 appendix A.1.1.2 very closely,
michael@0 1224 ** and so that the correctness of this code can be easily verified.
michael@0 1225 ** So, please forgive the ugly c code.
michael@0 1226 **/
michael@0 1227 static SECStatus
michael@0 1228 pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type,
michael@0 1229 unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy)
michael@0 1230 {
michael@0 1231 unsigned int n; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
michael@0 1232 unsigned int b; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
michael@0 1233 unsigned int seedlen; /* Per FIPS 186-3 app A.1.1.2 (was 'g' 186-1)*/
michael@0 1234 unsigned int counter; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
michael@0 1235 unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
michael@0 1236 unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */
michael@0 1237 unsigned int maxCount;
michael@0 1238 HASH_HashType hashtype;
michael@0 1239 SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
michael@0 1240 PLArenaPool *arena = NULL;
michael@0 1241 PQGParams *params = NULL;
michael@0 1242 PQGVerify *verify = NULL;
michael@0 1243 PRBool passed;
michael@0 1244 SECItem hit = { 0, 0, 0 };
michael@0 1245 SECItem firstseed = { 0, 0, 0 };
michael@0 1246 SECItem qseed = { 0, 0, 0 };
michael@0 1247 SECItem pseed = { 0, 0, 0 };
michael@0 1248 mp_int P, Q, G, H, l, p0;
michael@0 1249 mp_err err = MP_OKAY;
michael@0 1250 SECStatus rv = SECFailure;
michael@0 1251 int iterations = 0;
michael@0 1252
michael@0 1253
michael@0 1254 /* Step 1. L and N already checked by caller*/
michael@0 1255 /* Step 2. if (seedlen < N) return INVALID; */
michael@0 1256 if (seedBytes < N/PR_BITS_PER_BYTE || !pParams || !pVfy) {
michael@0 1257 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1258 return SECFailure;
michael@0 1259 }
michael@0 1260 /* Initialize an arena for the params. */
michael@0 1261 arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
michael@0 1262 if (!arena) {
michael@0 1263 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1264 return SECFailure;
michael@0 1265 }
michael@0 1266 params = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
michael@0 1267 if (!params) {
michael@0 1268 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1269 PORT_FreeArena(arena, PR_TRUE);
michael@0 1270 return SECFailure;
michael@0 1271 }
michael@0 1272 params->arena = arena;
michael@0 1273 /* Initialize an arena for the verify. */
michael@0 1274 arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
michael@0 1275 if (!arena) {
michael@0 1276 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1277 PORT_FreeArena(params->arena, PR_TRUE);
michael@0 1278 return SECFailure;
michael@0 1279 }
michael@0 1280 verify = (PQGVerify *)PORT_ArenaZAlloc(arena, sizeof(PQGVerify));
michael@0 1281 if (!verify) {
michael@0 1282 PORT_SetError(SEC_ERROR_NO_MEMORY);
michael@0 1283 PORT_FreeArena(arena, PR_TRUE);
michael@0 1284 PORT_FreeArena(params->arena, PR_TRUE);
michael@0 1285 return SECFailure;
michael@0 1286 }
michael@0 1287 verify->arena = arena;
michael@0 1288 seed = &verify->seed;
michael@0 1289 arena = NULL;
michael@0 1290 /* Initialize bignums */
michael@0 1291 MP_DIGITS(&P) = 0;
michael@0 1292 MP_DIGITS(&Q) = 0;
michael@0 1293 MP_DIGITS(&G) = 0;
michael@0 1294 MP_DIGITS(&H) = 0;
michael@0 1295 MP_DIGITS(&l) = 0;
michael@0 1296 MP_DIGITS(&p0) = 0;
michael@0 1297 CHECK_MPI_OK( mp_init(&P) );
michael@0 1298 CHECK_MPI_OK( mp_init(&Q) );
michael@0 1299 CHECK_MPI_OK( mp_init(&G) );
michael@0 1300 CHECK_MPI_OK( mp_init(&H) );
michael@0 1301 CHECK_MPI_OK( mp_init(&l) );
michael@0 1302 CHECK_MPI_OK( mp_init(&p0) );
michael@0 1303
michael@0 1304 /* Select Hash and Compute lengths. */
michael@0 1305 /* getFirstHash gives us the smallest acceptable hash for this key
michael@0 1306 * strength */
michael@0 1307 hashtype = getFirstHash(L,N);
michael@0 1308 outlen = HASH_ResultLen(hashtype)*PR_BITS_PER_BYTE;
michael@0 1309
michael@0 1310 /* Step 3: n = Ceil(L/outlen)-1; (same as n = Floor((L-1)/outlen)) */
michael@0 1311 n = (L - 1) / outlen;
michael@0 1312 /* Step 4: b = L -1 - (n*outlen); (same as n = (L-1) mod outlen) */
michael@0 1313 b = (L - 1) % outlen;
michael@0 1314 seedlen = seedBytes * PR_BITS_PER_BYTE; /* bits in seed */
michael@0 1315 step_5:
michael@0 1316 /* ******************************************************************
michael@0 1317 ** Step 5. (Step 1 in 186-1)
michael@0 1318 ** "Choose an abitrary sequence of at least N bits and call it SEED.
michael@0 1319 ** Let g be the length of SEED in bits."
michael@0 1320 */
michael@0 1321 if (++iterations > MAX_ITERATIONS) { /* give up after a while */
michael@0 1322 PORT_SetError(SEC_ERROR_NEED_RANDOM);
michael@0 1323 goto cleanup;
michael@0 1324 }
michael@0 1325 seed->len = seedBytes;
michael@0 1326 CHECK_SEC_OK( getPQseed(seed, verify->arena) );
michael@0 1327 /* ******************************************************************
michael@0 1328 ** Step 6. (Step 2 in 186-1)
michael@0 1329 **
michael@0 1330 ** "Compute U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]. (186-1)"
michael@0 1331 ** "Compute U = HASH[SEED] 2**(N-1). (186-3)"
michael@0 1332 **
michael@0 1333 ** Step 7. (Step 3 in 186-1)
michael@0 1334 ** "Form Q from U by setting the most signficant bit (the 2**159 bit)
michael@0 1335 ** and the least signficant bit to 1. In terms of boolean operations,
michael@0 1336 ** Q = U OR 2**159 OR 1. Note that 2**159 < Q < 2**160. (186-1)"
michael@0 1337 **
michael@0 1338 ** "q = 2**(N-1) + U + 1 - (U mod 2) (186-3)
michael@0 1339 **
michael@0 1340 ** Note: Both formulations are the same for U < 2**(N-1) and N=160
michael@0 1341 **
michael@0 1342 ** If using Shawe-Taylor, We do the entire A.1.2.1.2 setps in the block
michael@0 1343 ** FIPS186_3_ST_TYPE.
michael@0 1344 */
michael@0 1345 if (type == FIPS186_1_TYPE) {
michael@0 1346 CHECK_SEC_OK( makeQfromSeed(seedlen, seed, &Q) );
michael@0 1347 } else if (type == FIPS186_3_TYPE) {
michael@0 1348 CHECK_SEC_OK( makeQ2fromSeed(hashtype, N, seed, &Q) );
michael@0 1349 } else {
michael@0 1350 /* FIPS186_3_ST_TYPE */
michael@0 1351 int qgen_counter, pgen_counter;
michael@0 1352
michael@0 1353 /* Step 1 (L,N) already checked for acceptability */
michael@0 1354
michael@0 1355 firstseed = *seed;
michael@0 1356 qgen_counter = 0;
michael@0 1357 /* Step 2. Use N and firstseed to generate random prime q
michael@0 1358 * using Apendix C.6 */
michael@0 1359 CHECK_SEC_OK( makePrimefromSeedShaweTaylor(hashtype, N, &firstseed, &Q,
michael@0 1360 &qseed, &qgen_counter) );
michael@0 1361 /* Step 3. Use floor(L/2+1) and qseed to generate random prime p0
michael@0 1362 * using Appendix C.6 */
michael@0 1363 pgen_counter = 0;
michael@0 1364 CHECK_SEC_OK( makePrimefromSeedShaweTaylor(hashtype, (L+1)/2+1,
michael@0 1365 &qseed, &p0, &pseed, &pgen_counter) );
michael@0 1366 /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
michael@0 1367 CHECK_SEC_OK( makePrimefromPrimesShaweTaylor(hashtype, L,
michael@0 1368 &p0, &Q, &P, &pseed, &pgen_counter) );
michael@0 1369
michael@0 1370 /* combine all the seeds */
michael@0 1371 seed->len = firstseed.len +qseed.len + pseed.len;
michael@0 1372 seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
michael@0 1373 if (seed->data == NULL) {
michael@0 1374 goto cleanup;
michael@0 1375 }
michael@0 1376 PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
michael@0 1377 PORT_Memcpy(seed->data+firstseed.len, pseed.data, pseed.len);
michael@0 1378 PORT_Memcpy(seed->data+firstseed.len+pseed.len, qseed.data, qseed.len);
michael@0 1379 counter = 0 ; /* (qgen_counter << 16) | pgen_counter; */
michael@0 1380
michael@0 1381 /* we've generated both P and Q now, skip to generating G */
michael@0 1382 goto generate_G;
michael@0 1383 }
michael@0 1384 /* ******************************************************************
michael@0 1385 ** Step 8. (Step 4 in 186-1)
michael@0 1386 ** "Use a robust primality testing algorithm to test whether q is prime."
michael@0 1387 **
michael@0 1388 ** Appendix 2.1 states that a Rabin test with at least 50 iterations
michael@0 1389 ** "will give an acceptable probability of error."
michael@0 1390 */
michael@0 1391 /*CHECK_SEC_OK( prm_RabinTest(&Q, &passed) );*/
michael@0 1392 err = mpp_pprime(&Q, prime_testcount_q(L,N));
michael@0 1393 passed = (err == MP_YES) ? SECSuccess : SECFailure;
michael@0 1394 /* ******************************************************************
michael@0 1395 ** Step 9. (Step 5 in 186-1) "If q is not prime, goto step 5 (1 in 186-1)."
michael@0 1396 */
michael@0 1397 if (passed != SECSuccess)
michael@0 1398 goto step_5;
michael@0 1399 /* ******************************************************************
michael@0 1400 ** Step 10.
michael@0 1401 ** offset = 1;
michael@0 1402 **( Step 6b 186-1)"Let counter = 0 and offset = 2."
michael@0 1403 */
michael@0 1404 offset = (type == FIPS186_1_TYPE) ? 2 : 1;
michael@0 1405 /*
michael@0 1406 ** Step 11. (Step 6a,13a,14 in 186-1)
michael@0 1407 ** For counter - 0 to (4L-1) do
michael@0 1408 **
michael@0 1409 */
michael@0 1410 maxCount = L >= 1024 ? (4*L - 1) : 4095;
michael@0 1411 for (counter = 0; counter <= maxCount; counter++) {
michael@0 1412 /* ******************************************************************
michael@0 1413 ** Step 11.1 (Step 7 in 186-1)
michael@0 1414 ** "for j = 0 ... n let
michael@0 1415 ** V_j = HASH[(SEED + offset + j) mod 2**seedlen]."
michael@0 1416 **
michael@0 1417 ** Step 11.2 (Step 8 in 186-1)
michael@0 1418 ** "W = V_0 + V_1*2**outlen+...+ V_n-1 * 2**((n-1)*outlen) +
michael@0 1419 ** ((Vn* mod 2**b)*2**(n*outlen))"
michael@0 1420 ** Step 11.3 (Step 8 in 186-1)
michael@0 1421 ** "X = W + 2**(L-1)
michael@0 1422 ** Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L."
michael@0 1423 **
michael@0 1424 ** Step 11.4 (Step 9 in 186-1).
michael@0 1425 ** "c = X mod 2q"
michael@0 1426 **
michael@0 1427 ** Step 11.5 (Step 9 in 186-1).
michael@0 1428 ** " p = X - (c - 1).
michael@0 1429 ** Note that p is congruent to 1 mod 2q."
michael@0 1430 */
michael@0 1431 CHECK_SEC_OK( makePfromQandSeed(hashtype, L, N, offset, seedlen,
michael@0 1432 seed, &Q, &P) );
michael@0 1433 /*************************************************************
michael@0 1434 ** Step 11.6. (Step 10 in 186-1)
michael@0 1435 ** "if p < 2**(L-1), then goto step 11.9. (step 13 in 186-1)"
michael@0 1436 */
michael@0 1437 CHECK_MPI_OK( mpl_set_bit(&l, (mp_size)(L-1), 1) ); /* l = 2**(L-1) */
michael@0 1438 if (mp_cmp(&P, &l) < 0)
michael@0 1439 goto step_11_9;
michael@0 1440 /************************************************************
michael@0 1441 ** Step 11.7 (step 11 in 186-1)
michael@0 1442 ** "Perform a robust primality test on p."
michael@0 1443 */
michael@0 1444 /*CHECK_SEC_OK( prm_RabinTest(&P, &passed) );*/
michael@0 1445 err = mpp_pprime(&P, prime_testcount_p(L, N));
michael@0 1446 passed = (err == MP_YES) ? SECSuccess : SECFailure;
michael@0 1447 /* ******************************************************************
michael@0 1448 ** Step 11.8. "If p is determined to be primed return VALID
michael@0 1449 ** values of p, q, seed and counter."
michael@0 1450 */
michael@0 1451 if (passed == SECSuccess)
michael@0 1452 break;
michael@0 1453 step_11_9:
michael@0 1454 /* ******************************************************************
michael@0 1455 ** Step 11.9. "offset = offset + n + 1."
michael@0 1456 */
michael@0 1457 offset += n + 1;
michael@0 1458 }
michael@0 1459 /* ******************************************************************
michael@0 1460 ** Step 12. "goto step 5."
michael@0 1461 **
michael@0 1462 ** NOTE: if counter <= maxCount, then we exited the loop at Step 11.8
michael@0 1463 ** and now need to return p,q, seed, and counter.
michael@0 1464 */
michael@0 1465 if (counter > maxCount)
michael@0 1466 goto step_5;
michael@0 1467
michael@0 1468 generate_G:
michael@0 1469 /* ******************************************************************
michael@0 1470 ** returning p, q, seed and counter
michael@0 1471 */
michael@0 1472 if (type == FIPS186_1_TYPE) {
michael@0 1473 /* Generate g, This is called the "Unverifiable Generation of g
michael@0 1474 * in FIPA186-3 Appedix A.2.1. For compatibility we maintain
michael@0 1475 * this version of the code */
michael@0 1476 SECITEM_AllocItem(NULL, &hit, L/8); /* h is no longer than p */
michael@0 1477 if (!hit.data) goto cleanup;
michael@0 1478 do {
michael@0 1479 /* loop generate h until 1<h<p-1 and (h**[(p-1)/q])mod p > 1 */
michael@0 1480 CHECK_SEC_OK( generate_h_candidate(&hit, &H) );
michael@0 1481 CHECK_SEC_OK( makeGfromH(&P, &Q, &H, &G, &passed) );
michael@0 1482 } while (passed != PR_TRUE);
michael@0 1483 MPINT_TO_SECITEM(&H, &verify->h, verify->arena);
michael@0 1484 } else {
michael@0 1485 unsigned char index = 1; /* default to 1 */
michael@0 1486 verify->h.data = (unsigned char *)PORT_ArenaZAlloc(verify->arena, 1);
michael@0 1487 if (verify->h.data == NULL) { goto cleanup; }
michael@0 1488 verify->h.len = 1;
michael@0 1489 verify->h.data[0] = index;
michael@0 1490 /* Generate g, using the FIPS 186-3 Appendix A.23 */
michael@0 1491 CHECK_SEC_OK(makeGfromIndex(hashtype, &P, &Q, seed, index, &G) );
michael@0 1492 }
michael@0 1493 /* All generation is done. Now, save the PQG params. */
michael@0 1494 MPINT_TO_SECITEM(&P, &params->prime, params->arena);
michael@0 1495 MPINT_TO_SECITEM(&Q, &params->subPrime, params->arena);
michael@0 1496 MPINT_TO_SECITEM(&G, &params->base, params->arena);
michael@0 1497 verify->counter = counter;
michael@0 1498 *pParams = params;
michael@0 1499 *pVfy = verify;
michael@0 1500 cleanup:
michael@0 1501 if (pseed.data) {
michael@0 1502 PORT_Free(pseed.data);
michael@0 1503 }
michael@0 1504 if (qseed.data) {
michael@0 1505 PORT_Free(qseed.data);
michael@0 1506 }
michael@0 1507 mp_clear(&P);
michael@0 1508 mp_clear(&Q);
michael@0 1509 mp_clear(&G);
michael@0 1510 mp_clear(&H);
michael@0 1511 mp_clear(&l);
michael@0 1512 mp_clear(&p0);
michael@0 1513 if (err) {
michael@0 1514 MP_TO_SEC_ERROR(err);
michael@0 1515 rv = SECFailure;
michael@0 1516 }
michael@0 1517 if (rv) {
michael@0 1518 PORT_FreeArena(params->arena, PR_TRUE);
michael@0 1519 PORT_FreeArena(verify->arena, PR_TRUE);
michael@0 1520 }
michael@0 1521 if (hit.data) {
michael@0 1522 SECITEM_FreeItem(&hit, PR_FALSE);
michael@0 1523 }
michael@0 1524 return rv;
michael@0 1525 }
michael@0 1526
michael@0 1527 SECStatus
michael@0 1528 PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy)
michael@0 1529 {
michael@0 1530 unsigned int L; /* Length of P in bits. Per FIPS 186. */
michael@0 1531 unsigned int seedBytes;
michael@0 1532
michael@0 1533 if (j > 8 || !pParams || !pVfy) {
michael@0 1534 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1535 return SECFailure;
michael@0 1536 }
michael@0 1537 L = 512 + (j * 64); /* bits in P */
michael@0 1538 seedBytes = L/8;
michael@0 1539 return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes,
michael@0 1540 pParams, pVfy);
michael@0 1541 }
michael@0 1542
michael@0 1543 SECStatus
michael@0 1544 PQG_ParamGenSeedLen(unsigned int j, unsigned int seedBytes,
michael@0 1545 PQGParams **pParams, PQGVerify **pVfy)
michael@0 1546 {
michael@0 1547 unsigned int L; /* Length of P in bits. Per FIPS 186. */
michael@0 1548
michael@0 1549 if (j > 8 || !pParams || !pVfy) {
michael@0 1550 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1551 return SECFailure;
michael@0 1552 }
michael@0 1553 L = 512 + (j * 64); /* bits in P */
michael@0 1554 return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes,
michael@0 1555 pParams, pVfy);
michael@0 1556 }
michael@0 1557
michael@0 1558 SECStatus
michael@0 1559 PQG_ParamGenV2(unsigned int L, unsigned int N, unsigned int seedBytes,
michael@0 1560 PQGParams **pParams, PQGVerify **pVfy)
michael@0 1561 {
michael@0 1562 if (N == 0) {
michael@0 1563 N = pqg_get_default_N(L);
michael@0 1564 }
michael@0 1565 if (seedBytes == 0) {
michael@0 1566 /* seedBytes == L/8 for probable primes, N/8 for Shawe-Taylor Primes */
michael@0 1567 seedBytes = N/8;
michael@0 1568 }
michael@0 1569 if (pqg_validate_dsa2(L,N) != SECSuccess) {
michael@0 1570 /* error code already set */
michael@0 1571 return SECFailure;
michael@0 1572 }
michael@0 1573 return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy);
michael@0 1574 }
michael@0 1575
michael@0 1576
michael@0 1577 /*
michael@0 1578 * verify can use vfy structures returned from either FIPS186-1 or
michael@0 1579 * FIPS186-2, and can handle differences in selected Hash functions to
michael@0 1580 * generate the parameters.
michael@0 1581 */
michael@0 1582 SECStatus
michael@0 1583 PQG_VerifyParams(const PQGParams *params,
michael@0 1584 const PQGVerify *vfy, SECStatus *result)
michael@0 1585 {
michael@0 1586 SECStatus rv = SECSuccess;
michael@0 1587 unsigned int g, n, L, N, offset, outlen;
michael@0 1588 mp_int p0, P, Q, G, P_, Q_, G_, r, h;
michael@0 1589 mp_err err = MP_OKAY;
michael@0 1590 int j;
michael@0 1591 unsigned int counter_max = 0; /* handle legacy L < 1024 */
michael@0 1592 int qseed_len;
michael@0 1593 SECItem pseed_ = {0, 0, 0};
michael@0 1594 HASH_HashType hashtype;
michael@0 1595 pqgGenType type;
michael@0 1596
michael@0 1597 #define CHECKPARAM(cond) \
michael@0 1598 if (!(cond)) { \
michael@0 1599 *result = SECFailure; \
michael@0 1600 goto cleanup; \
michael@0 1601 }
michael@0 1602 if (!params || !vfy || !result) {
michael@0 1603 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1604 return SECFailure;
michael@0 1605 }
michael@0 1606 /* always need at least p, q, and seed for any meaningful check */
michael@0 1607 if ((params->prime.len == 0) || (params->subPrime.len == 0) ||
michael@0 1608 (vfy->seed.len == 0)) {
michael@0 1609 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1610 return SECFailure;
michael@0 1611 }
michael@0 1612 /* we want to either check PQ or G or both. If we don't have G, make
michael@0 1613 * sure we have count so we can check P. */
michael@0 1614 if ((params->base.len == 0) && (vfy->counter == -1)) {
michael@0 1615 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1616 return SECFailure;
michael@0 1617 }
michael@0 1618
michael@0 1619 MP_DIGITS(&p0) = 0;
michael@0 1620 MP_DIGITS(&P) = 0;
michael@0 1621 MP_DIGITS(&Q) = 0;
michael@0 1622 MP_DIGITS(&G) = 0;
michael@0 1623 MP_DIGITS(&P_) = 0;
michael@0 1624 MP_DIGITS(&Q_) = 0;
michael@0 1625 MP_DIGITS(&G_) = 0;
michael@0 1626 MP_DIGITS(&r) = 0;
michael@0 1627 MP_DIGITS(&h) = 0;
michael@0 1628 CHECK_MPI_OK( mp_init(&p0) );
michael@0 1629 CHECK_MPI_OK( mp_init(&P) );
michael@0 1630 CHECK_MPI_OK( mp_init(&Q) );
michael@0 1631 CHECK_MPI_OK( mp_init(&G) );
michael@0 1632 CHECK_MPI_OK( mp_init(&P_) );
michael@0 1633 CHECK_MPI_OK( mp_init(&Q_) );
michael@0 1634 CHECK_MPI_OK( mp_init(&G_) );
michael@0 1635 CHECK_MPI_OK( mp_init(&r) );
michael@0 1636 CHECK_MPI_OK( mp_init(&h) );
michael@0 1637 *result = SECSuccess;
michael@0 1638 SECITEM_TO_MPINT(params->prime, &P);
michael@0 1639 SECITEM_TO_MPINT(params->subPrime, &Q);
michael@0 1640 /* if G isn't specified, just check P and Q */
michael@0 1641 if (params->base.len != 0) {
michael@0 1642 SECITEM_TO_MPINT(params->base, &G);
michael@0 1643 }
michael@0 1644 /* 1. Check (L,N) pair */
michael@0 1645 N = mpl_significant_bits(&Q);
michael@0 1646 L = mpl_significant_bits(&P);
michael@0 1647 if (L < 1024) {
michael@0 1648 /* handle DSA1 pqg parameters with less thatn 1024 bits*/
michael@0 1649 CHECKPARAM( N == DSA1_Q_BITS );
michael@0 1650 j = PQG_PBITS_TO_INDEX(L);
michael@0 1651 CHECKPARAM( j >= 0 && j <= 8 );
michael@0 1652 counter_max = 4096;
michael@0 1653 } else {
michael@0 1654 /* handle DSA2 parameters (includes DSA1, 1024 bits) */
michael@0 1655 CHECKPARAM(pqg_validate_dsa2(L, N) == SECSuccess);
michael@0 1656 counter_max = 4*L;
michael@0 1657 }
michael@0 1658 /* 3. G < P */
michael@0 1659 if (params->base.len != 0) {
michael@0 1660 CHECKPARAM( mp_cmp(&G, &P) < 0 );
michael@0 1661 }
michael@0 1662 /* 4. P % Q == 1 */
michael@0 1663 CHECK_MPI_OK( mp_mod(&P, &Q, &r) );
michael@0 1664 CHECKPARAM( mp_cmp_d(&r, 1) == 0 );
michael@0 1665 /* 5. Q is prime */
michael@0 1666 CHECKPARAM( mpp_pprime(&Q, prime_testcount_q(L,N)) == MP_YES );
michael@0 1667 /* 6. P is prime */
michael@0 1668 CHECKPARAM( mpp_pprime(&P, prime_testcount_p(L,N)) == MP_YES );
michael@0 1669 /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
michael@0 1670 /* continue processing P */
michael@0 1671 /* 7. counter < 4*L */
michael@0 1672 CHECKPARAM( (vfy->counter == -1) || (vfy->counter < counter_max) );
michael@0 1673 /* 8. g >= N and g < 2*L (g is length of seed in bits) */
michael@0 1674 g = vfy->seed.len * 8;
michael@0 1675 CHECKPARAM( g >= N && g < counter_max/2 );
michael@0 1676 /* 9. Q generated from SEED matches Q in PQGParams. */
michael@0 1677 /* This function checks all possible hash and generation types to
michael@0 1678 * find a Q_ which matches Q. */
michael@0 1679 CHECKPARAM( findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
michael@0 1680 &hashtype, &type) == SECSuccess );
michael@0 1681 CHECKPARAM( mp_cmp(&Q, &Q_) == 0 );
michael@0 1682 if (type == FIPS186_3_ST_TYPE) {
michael@0 1683 SECItem qseed = { 0, 0, 0 };
michael@0 1684 SECItem pseed = { 0, 0, 0 };
michael@0 1685 int first_seed_len;
michael@0 1686 int pgen_counter = 0;
michael@0 1687
michael@0 1688 /* extract pseed and qseed from domain_parameter_seed, which is
michael@0 1689 * first_seed || pseed || qseed. qseed is first_seed + small_integer
michael@0 1690 * pseed is qseed + small_integer. This means most of the time
michael@0 1691 * first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
michael@0 1692 * pseed.len will be one greater than first_seed.len, so we can
michael@0 1693 * depend on the fact that
michael@0 1694 * first_seed.len = floor(domain_parameter_seed.len/3).
michael@0 1695 * findQfromSeed returned qseed.len, so we can calculate pseed.len as
michael@0 1696 * pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
michael@0 1697 * this is probably over kill, since 99.999% of the time they will all
michael@0 1698 * be equal.
michael@0 1699 *
michael@0 1700 * With the lengths, we can now find the offsets;
michael@0 1701 * first_seed.data = domain_parameter_seed.data + 0
michael@0 1702 * pseed.data = domain_parameter_seed.data + first_seed.len
michael@0 1703 * qseed.data = domain_parameter_seed.data
michael@0 1704 * + domain_paramter_seed.len - qseed.len
michael@0 1705 *
michael@0 1706 */
michael@0 1707 first_seed_len = vfy->seed.len/3;
michael@0 1708 CHECKPARAM(qseed_len < vfy->seed.len);
michael@0 1709 CHECKPARAM(first_seed_len*8 > N-1);
michael@0 1710 CHECKPARAM(first_seed_len+qseed_len < vfy->seed.len);
michael@0 1711 qseed.len = qseed_len;
michael@0 1712 qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
michael@0 1713 pseed.len = vfy->seed.len - (first_seed_len+qseed_len);
michael@0 1714 pseed.data = vfy->seed.data + first_seed_len;
michael@0 1715
michael@0 1716 /*
michael@0 1717 * now complete FIPS 186-3 A.1.2.1.2. Step 1 was completed
michael@0 1718 * above in our initial checks, Step 2 was completed by
michael@0 1719 * findQfromSeed */
michael@0 1720
michael@0 1721 /* Step 3 (status, c0, prime_seed, prime_gen_counter) =
michael@0 1722 ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
michael@0 1723 */
michael@0 1724 CHECK_SEC_OK( makePrimefromSeedShaweTaylor(hashtype, (L+1)/2+1,
michael@0 1725 &qseed, &p0, &pseed_, &pgen_counter) );
michael@0 1726 /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
michael@0 1727 CHECK_SEC_OK( makePrimefromPrimesShaweTaylor(hashtype, L,
michael@0 1728 &p0, &Q_, &P_, &pseed_, &pgen_counter) );
michael@0 1729 CHECKPARAM( mp_cmp(&P, &P_) == 0 );
michael@0 1730 /* make sure pseed wasn't tampered with (since it is part of
michael@0 1731 * calculating G) */
michael@0 1732 CHECKPARAM( SECITEM_CompareItem(&pseed, &pseed_) == SECEqual );
michael@0 1733 } else if (vfy->counter == -1) {
michael@0 1734 /* If counter is set to -1, we are really only verifying G, skip
michael@0 1735 * the remainder of the checks for P */
michael@0 1736 CHECKPARAM(type != FIPS186_1_TYPE); /* we only do this for DSA2 */
michael@0 1737 } else {
michael@0 1738 /* 10. P generated from (L, counter, g, SEED, Q) matches P
michael@0 1739 * in PQGParams. */
michael@0 1740 outlen = HASH_ResultLen(hashtype)*PR_BITS_PER_BYTE;
michael@0 1741 n = (L - 1) / outlen;
michael@0 1742 offset = vfy->counter * (n + 1) + ((type == FIPS186_1_TYPE) ? 2 : 1);
michael@0 1743 CHECK_SEC_OK( makePfromQandSeed(hashtype, L, N, offset, g, &vfy->seed,
michael@0 1744 &Q, &P_) );
michael@0 1745 CHECKPARAM( mp_cmp(&P, &P_) == 0 );
michael@0 1746 }
michael@0 1747
michael@0 1748 /* now check G, skip if don't have a g */
michael@0 1749 if (params->base.len == 0) goto cleanup;
michael@0 1750
michael@0 1751 /* first Always check that G is OK FIPS186-3 A.2.2 & A.2.4*/
michael@0 1752 /* 1. 2 < G < P-1 */
michael@0 1753 /* P is prime, p-1 == zero 1st bit */
michael@0 1754 CHECK_MPI_OK( mpl_set_bit(&P, 0, 0) );
michael@0 1755 CHECKPARAM( mp_cmp_d(&G, 2) > 0 && mp_cmp(&G, &P) < 0 );
michael@0 1756 CHECK_MPI_OK( mpl_set_bit(&P, 0, 1) ); /* set it back */
michael@0 1757 /* 2. verify g**q mod p == 1 */
michael@0 1758 CHECK_MPI_OK( mp_exptmod(&G, &Q, &P, &h) ); /* h = G ** Q mod P */
michael@0 1759 CHECKPARAM(mp_cmp_d(&h, 1) == 0);
michael@0 1760
michael@0 1761 /* no h, the above is the best we can do */
michael@0 1762 if (vfy->h.len == 0) {
michael@0 1763 if (type != FIPS186_1_TYPE) {
michael@0 1764 *result = SECWouldBlock;
michael@0 1765 }
michael@0 1766 goto cleanup;
michael@0 1767 }
michael@0 1768
michael@0 1769 /*
michael@0 1770 * If h is one byte and FIPS186-3 was used to generate Q (we've verified
michael@0 1771 * Q was generated from seed already, then we assume that FIPS 186-3
michael@0 1772 * appendix A.2.3 was used to generate G. Otherwise we assume A.2.1 was
michael@0 1773 * used to generate G.
michael@0 1774 */
michael@0 1775 if ((vfy->h.len == 1) && (type != FIPS186_1_TYPE)) {
michael@0 1776 /* A.2.3 */
michael@0 1777 CHECK_SEC_OK(makeGfromIndex(hashtype, &P, &Q, &vfy->seed,
michael@0 1778 vfy->h.data[0], &G_) );
michael@0 1779 CHECKPARAM( mp_cmp(&G, &G_) == 0 );
michael@0 1780 } else {
michael@0 1781 int passed;
michael@0 1782 /* A.2.1 */
michael@0 1783 SECITEM_TO_MPINT(vfy->h, &h);
michael@0 1784 /* 11. 1 < h < P-1 */
michael@0 1785 /* P is prime, p-1 == zero 1st bit */
michael@0 1786 CHECK_MPI_OK( mpl_set_bit(&P, 0, 0) );
michael@0 1787 CHECKPARAM( mp_cmp_d(&G, 2) > 0 && mp_cmp(&G, &P) );
michael@0 1788 CHECK_MPI_OK( mpl_set_bit(&P, 0, 1) ); /* set it back */
michael@0 1789 /* 12. G generated from h matches G in PQGParams. */
michael@0 1790 CHECK_SEC_OK( makeGfromH(&P, &Q, &h, &G_, &passed) );
michael@0 1791 CHECKPARAM( passed && mp_cmp(&G, &G_) == 0 );
michael@0 1792 }
michael@0 1793 cleanup:
michael@0 1794 mp_clear(&p0);
michael@0 1795 mp_clear(&P);
michael@0 1796 mp_clear(&Q);
michael@0 1797 mp_clear(&G);
michael@0 1798 mp_clear(&P_);
michael@0 1799 mp_clear(&Q_);
michael@0 1800 mp_clear(&G_);
michael@0 1801 mp_clear(&r);
michael@0 1802 mp_clear(&h);
michael@0 1803 if (pseed_.data) {
michael@0 1804 SECITEM_FreeItem(&pseed_,PR_FALSE);
michael@0 1805 }
michael@0 1806 if (err) {
michael@0 1807 MP_TO_SEC_ERROR(err);
michael@0 1808 rv = SECFailure;
michael@0 1809 }
michael@0 1810 return rv;
michael@0 1811 }
michael@0 1812
michael@0 1813 /**************************************************************************
michael@0 1814 * Free the PQGParams struct and the things it points to. *
michael@0 1815 **************************************************************************/
michael@0 1816 void
michael@0 1817 PQG_DestroyParams(PQGParams *params)
michael@0 1818 {
michael@0 1819 if (params == NULL)
michael@0 1820 return;
michael@0 1821 if (params->arena != NULL) {
michael@0 1822 PORT_FreeArena(params->arena, PR_FALSE); /* don't zero it */
michael@0 1823 } else {
michael@0 1824 SECITEM_FreeItem(&params->prime, PR_FALSE); /* don't free prime */
michael@0 1825 SECITEM_FreeItem(&params->subPrime, PR_FALSE); /* don't free subPrime */
michael@0 1826 SECITEM_FreeItem(&params->base, PR_FALSE); /* don't free base */
michael@0 1827 PORT_Free(params);
michael@0 1828 }
michael@0 1829 }
michael@0 1830
michael@0 1831 /**************************************************************************
michael@0 1832 * Free the PQGVerify struct and the things it points to. *
michael@0 1833 **************************************************************************/
michael@0 1834
michael@0 1835 void
michael@0 1836 PQG_DestroyVerify(PQGVerify *vfy)
michael@0 1837 {
michael@0 1838 if (vfy == NULL)
michael@0 1839 return;
michael@0 1840 if (vfy->arena != NULL) {
michael@0 1841 PORT_FreeArena(vfy->arena, PR_FALSE); /* don't zero it */
michael@0 1842 } else {
michael@0 1843 SECITEM_FreeItem(&vfy->seed, PR_FALSE); /* don't free seed */
michael@0 1844 SECITEM_FreeItem(&vfy->h, PR_FALSE); /* don't free h */
michael@0 1845 PORT_Free(vfy);
michael@0 1846 }
michael@0 1847 }

mercurial