Thu, 22 Jan 2015 13:21:57 +0100
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(¶ms->prime)*PR_BITS_PER_BYTE; |
michael@0 | 232 | N = PQG_GetLength(¶ms->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(¶ms->prime)*PR_BITS_PER_BYTE; |
michael@0 | 265 | N = PQG_GetLength(¶ms->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, ¶ms->prime, params->arena); |
michael@0 | 1495 | MPINT_TO_SECITEM(&Q, ¶ms->subPrime, params->arena); |
michael@0 | 1496 | MPINT_TO_SECITEM(&G, ¶ms->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(¶ms->prime, PR_FALSE); /* don't free prime */ |
michael@0 | 1825 | SECITEM_FreeItem(¶ms->subPrime, PR_FALSE); /* don't free subPrime */ |
michael@0 | 1826 | SECITEM_FreeItem(¶ms->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 | } |