/src/openssl/crypto/ffc/ffc_params_generate.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | /* |
11 | | * For the prime check.. |
12 | | * FIPS 186-4 Section C.3 Table C.1 |
13 | | * Returns the minimum number of Miller Rabin iterations for a L,N pair |
14 | | * (where L = len(p), N = len(q)) |
15 | | * L N Min |
16 | | * 1024 160 40 |
17 | | * 2048 224 56 |
18 | | * 2048 256 56 |
19 | | * 3072 256 64 |
20 | | * |
21 | | * BN_check_prime() uses: |
22 | | * 64 iterations for L <= 2048 OR |
23 | | * 128 iterations for L > 2048 |
24 | | * So this satisfies the requirement. |
25 | | */ |
26 | | |
27 | | #include <string.h> /* memset */ |
28 | | #include <openssl/sha.h> /* SHA_DIGEST_LENGTH */ |
29 | | #include <openssl/rand.h> |
30 | | #include <openssl/err.h> |
31 | | #include <openssl/dherr.h> |
32 | | #include <openssl/dsaerr.h> |
33 | | #include "crypto/bn.h" |
34 | | #include "internal/ffc.h" |
35 | | |
36 | | /* |
37 | | * Verify that the passed in L, N pair for DH or DSA is valid. |
38 | | * Returns 0 if invalid, otherwise it returns the security strength. |
39 | | */ |
40 | | |
41 | | #ifdef FIPS_MODULE |
42 | | static int ffc_validate_LN(size_t L, size_t N, int type, int verify) |
43 | | { |
44 | | if (type == FFC_PARAM_TYPE_DH) { |
45 | | /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */ |
46 | | if (L == 2048 && (N == 224 || N == 256)) |
47 | | return 112; |
48 | | #ifndef OPENSSL_NO_DH |
49 | | ERR_raise_data(ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS, |
50 | | "(L, N)=(%zu, %zu) should be (2048, 224) or (2048, 256)", L, N); |
51 | | #endif |
52 | | } else if (type == FFC_PARAM_TYPE_DSA) { |
53 | | /* Valid DSA L,N parameters from FIPS 186-4 Section 4.2 */ |
54 | | /* In fips mode 1024/160 can only be used for verification */ |
55 | | if (verify && L == 1024 && N == 160) |
56 | | return 80; |
57 | | if (L == 2048 && (N == 224 || N == 256)) |
58 | | return 112; |
59 | | if (L == 3072 && N == 256) |
60 | | return 128; |
61 | | #ifndef OPENSSL_NO_DSA |
62 | | ERR_raise_data(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS, |
63 | | "(L, N)=(%zu, %zu) should be (1024, 160) (for verification only), " |
64 | | "(2048, 224), (2048, 256), or (3072, 256)", |
65 | | L, N); |
66 | | #endif |
67 | | } |
68 | | return 0; |
69 | | } |
70 | | #else |
71 | | static int ffc_validate_LN(size_t L, size_t N, int type, int verify) |
72 | 0 | { |
73 | 0 | if (type == FFC_PARAM_TYPE_DH) { |
74 | | /* Allow legacy 1024/160 in non fips mode */ |
75 | 0 | if (L == 1024 && N == 160) |
76 | 0 | return 80; |
77 | | /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */ |
78 | 0 | if (L == 2048 && (N == 224 || N == 256)) |
79 | 0 | return 112; |
80 | 0 | #ifndef OPENSSL_NO_DH |
81 | 0 | ERR_raise_data(ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS, |
82 | 0 | "(L, N)=(%zu, %zu) should be (1024, 160), (2048, 224), or " |
83 | 0 | "(2048, 256)", |
84 | 0 | L, N); |
85 | 0 | #endif |
86 | 0 | } else if (type == FFC_PARAM_TYPE_DSA) { |
87 | 0 | if (N > 512) { |
88 | 0 | #ifndef OPENSSL_NO_DSA |
89 | 0 | ERR_raise_data(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS, |
90 | 0 | "N is %zu, but the maximum supported N is 512", N); |
91 | 0 | #endif |
92 | 0 | return 0; |
93 | 0 | } |
94 | 0 | if (L >= 3072 && N >= 256) |
95 | 0 | return 128; |
96 | 0 | if (L >= 2048 && N >= 224) |
97 | 0 | return 112; |
98 | 0 | if (L >= 1024 && N >= 160) |
99 | 0 | return 80; |
100 | 0 | #ifndef OPENSSL_NO_DSA |
101 | 0 | ERR_raise_data(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS, |
102 | 0 | "(L, N)=(%zu, %zu) should be at least (1024, 160)", L, N); |
103 | 0 | #endif |
104 | 0 | } |
105 | 0 | return 0; |
106 | 0 | } |
107 | | #endif /* FIPS_MODULE */ |
108 | | |
109 | | /* FIPS186-4 A.2.1 Unverifiable Generation of Generator g */ |
110 | | static int generate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, BIGNUM *g, |
111 | | BIGNUM *hbn, const BIGNUM *p, |
112 | | const BIGNUM *e, const BIGNUM *pm1, |
113 | | int *hret) |
114 | 0 | { |
115 | 0 | int h = 2; |
116 | | |
117 | | /* Step (2): choose h (where 1 < h)*/ |
118 | 0 | if (!BN_set_word(hbn, h)) |
119 | 0 | return 0; |
120 | | |
121 | 0 | for (;;) { |
122 | | /* Step (3): g = h^e % p */ |
123 | 0 | if (!BN_mod_exp_mont(g, hbn, e, p, ctx, mont)) |
124 | 0 | return 0; |
125 | | /* Step (4): Finish if g > 1 */ |
126 | 0 | if (BN_cmp(g, BN_value_one()) > 0) |
127 | 0 | break; |
128 | | |
129 | | /* Step (2) Choose any h in the range 1 < h < (p-1) */ |
130 | 0 | if (!BN_add_word(hbn, 1) || BN_cmp(hbn, pm1) >= 0) |
131 | 0 | return 0; |
132 | 0 | ++h; |
133 | 0 | } |
134 | 0 | *hret = h; |
135 | 0 | return 1; |
136 | 0 | } |
137 | | |
138 | | /* |
139 | | * FIPS186-4 A.2 Generation of canonical generator g. |
140 | | * |
141 | | * It requires the following values as input: |
142 | | * 'evpmd' digest, 'p' prime, 'e' cofactor, gindex and seed. |
143 | | * tmp is a passed in temporary BIGNUM. |
144 | | * mont is used in a BN_mod_exp_mont() with a modulus of p. |
145 | | * Returns a value in g. |
146 | | */ |
147 | | static int generate_canonical_g(BN_CTX *ctx, BN_MONT_CTX *mont, |
148 | | const EVP_MD *evpmd, BIGNUM *g, BIGNUM *tmp, |
149 | | const BIGNUM *p, const BIGNUM *e, |
150 | | int gindex, unsigned char *seed, size_t seedlen) |
151 | 0 | { |
152 | 0 | int ret = 0; |
153 | 0 | int counter = 1; |
154 | 0 | unsigned char md[EVP_MAX_MD_SIZE]; |
155 | 0 | EVP_MD_CTX *mctx = NULL; |
156 | 0 | int mdsize; |
157 | |
|
158 | 0 | mdsize = EVP_MD_get_size(evpmd); |
159 | 0 | if (mdsize <= 0) |
160 | 0 | return 0; |
161 | | |
162 | 0 | mctx = EVP_MD_CTX_new(); |
163 | 0 | if (mctx == NULL) |
164 | 0 | return 0; |
165 | | |
166 | | /* |
167 | | * A.2.3 Step (4) & (5) |
168 | | * A.2.4 Step (6) & (7) |
169 | | * counter = 0; counter += 1 |
170 | | */ |
171 | 0 | for (counter = 1; counter <= 0xFFFF; ++counter) { |
172 | | /* |
173 | | * A.2.3 Step (7) & (8) & (9) |
174 | | * A.2.4 Step (9) & (10) & (11) |
175 | | * W = Hash(seed || "ggen" || index || counter) |
176 | | * g = W^e % p |
177 | | */ |
178 | 0 | static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e }; |
179 | |
|
180 | 0 | md[0] = (unsigned char)(gindex & 0xff); |
181 | 0 | md[1] = (unsigned char)((counter >> 8) & 0xff); |
182 | 0 | md[2] = (unsigned char)(counter & 0xff); |
183 | 0 | if (!EVP_DigestInit_ex(mctx, evpmd, NULL) |
184 | 0 | || !EVP_DigestUpdate(mctx, seed, seedlen) |
185 | 0 | || !EVP_DigestUpdate(mctx, ggen, sizeof(ggen)) |
186 | 0 | || !EVP_DigestUpdate(mctx, md, 3) |
187 | 0 | || !EVP_DigestFinal_ex(mctx, md, NULL) |
188 | 0 | || (BN_bin2bn(md, mdsize, tmp) == NULL) |
189 | 0 | || !BN_mod_exp_mont(g, tmp, e, p, ctx, mont)) |
190 | 0 | break; /* exit on failure */ |
191 | | /* |
192 | | * A.2.3 Step (10) |
193 | | * A.2.4 Step (12) |
194 | | * Found a value for g if (g >= 2) |
195 | | */ |
196 | 0 | if (BN_cmp(g, BN_value_one()) > 0) { |
197 | 0 | ret = 1; |
198 | 0 | break; /* found g */ |
199 | 0 | } |
200 | 0 | } |
201 | 0 | EVP_MD_CTX_free(mctx); |
202 | 0 | return ret; |
203 | 0 | } |
204 | | |
205 | | /* Generation of p is the same for FIPS 186-4 & FIPS 186-2 */ |
206 | | static int generate_p(BN_CTX *ctx, const EVP_MD *evpmd, int max_counter, int n, |
207 | | unsigned char *buf, size_t buf_len, const BIGNUM *q, |
208 | | BIGNUM *p, int L, BN_GENCB *cb, int *counter, |
209 | | int *res) |
210 | 0 | { |
211 | 0 | int ret = -1; |
212 | 0 | int i, j, k, r; |
213 | 0 | unsigned char md[EVP_MAX_MD_SIZE]; |
214 | 0 | int mdsize; |
215 | 0 | BIGNUM *W, *X, *tmp, *c, *test; |
216 | |
|
217 | 0 | BN_CTX_start(ctx); |
218 | 0 | W = BN_CTX_get(ctx); |
219 | 0 | X = BN_CTX_get(ctx); |
220 | 0 | c = BN_CTX_get(ctx); |
221 | 0 | test = BN_CTX_get(ctx); |
222 | 0 | tmp = BN_CTX_get(ctx); |
223 | 0 | if (tmp == NULL) |
224 | 0 | goto err; |
225 | | |
226 | 0 | if (!BN_lshift(test, BN_value_one(), L - 1)) |
227 | 0 | goto err; |
228 | | |
229 | 0 | mdsize = EVP_MD_get_size(evpmd); |
230 | 0 | if (mdsize <= 0) |
231 | 0 | goto err; |
232 | | |
233 | | /* A.1.1.2 Step (10) AND |
234 | | * A.1.1.2 Step (12) |
235 | | * offset = 1 (this is handled below) |
236 | | */ |
237 | | /* |
238 | | * A.1.1.2 Step (11) AND |
239 | | * A.1.1.3 Step (13) |
240 | | */ |
241 | 0 | for (i = 0; i <= max_counter; i++) { |
242 | 0 | if ((i != 0) && !BN_GENCB_call(cb, 0, i)) |
243 | 0 | goto err; |
244 | | |
245 | 0 | BN_zero(W); |
246 | | /* seed_tmp buffer contains "seed + offset - 1" */ |
247 | 0 | for (j = 0; j <= n; j++) { |
248 | | /* obtain "seed + offset + j" by incrementing by 1: */ |
249 | 0 | for (k = (int)buf_len - 1; k >= 0; k--) { |
250 | 0 | buf[k]++; |
251 | 0 | if (buf[k] != 0) |
252 | 0 | break; |
253 | 0 | } |
254 | | /* |
255 | | * A.1.1.2 Step (11.1) AND |
256 | | * A.1.1.3 Step (13.1) |
257 | | * tmp = V(j) = Hash((seed + offset + j) % 2^seedlen) |
258 | | */ |
259 | 0 | if (!EVP_Digest(buf, buf_len, md, NULL, evpmd, NULL) |
260 | 0 | || (BN_bin2bn(md, mdsize, tmp) == NULL) |
261 | | /* |
262 | | * A.1.1.2 Step (11.2) |
263 | | * A.1.1.3 Step (13.2) |
264 | | * W += V(j) * 2^(outlen * j) |
265 | | */ |
266 | 0 | || !BN_lshift(tmp, tmp, (mdsize << 3) * j) |
267 | 0 | || !BN_add(W, W, tmp)) |
268 | 0 | goto err; |
269 | 0 | } |
270 | | |
271 | | /* |
272 | | * A.1.1.2 Step (11.3) AND |
273 | | * A.1.1.3 Step (13.3) |
274 | | * X = W + 2^(L-1) where W < 2^(L-1) |
275 | | */ |
276 | 0 | if (!BN_mask_bits(W, L - 1) |
277 | 0 | || BN_copy(X, W) == NULL |
278 | 0 | || !BN_add(X, X, test) |
279 | | /* |
280 | | * A.1.1.2 Step (11.4) AND |
281 | | * A.1.1.3 Step (13.4) |
282 | | * c = X mod 2q |
283 | | */ |
284 | 0 | || !BN_lshift1(tmp, q) |
285 | 0 | || !BN_mod(c, X, tmp, ctx) |
286 | | /* |
287 | | * A.1.1.2 Step (11.5) AND |
288 | | * A.1.1.3 Step (13.5) |
289 | | * p = X - (c - 1) |
290 | | */ |
291 | 0 | || !BN_sub(tmp, c, BN_value_one()) |
292 | 0 | || !BN_sub(p, X, tmp)) |
293 | 0 | goto err; |
294 | | |
295 | | /* |
296 | | * A.1.1.2 Step (11.6) AND |
297 | | * A.1.1.3 Step (13.6) |
298 | | * if (p < 2 ^ (L-1)) continue |
299 | | * This makes sure the top bit is set. |
300 | | */ |
301 | 0 | if (BN_cmp(p, test) >= 0) { |
302 | | /* |
303 | | * A.1.1.2 Step (11.7) AND |
304 | | * A.1.1.3 Step (13.7) |
305 | | * Test if p is prime |
306 | | * (This also makes sure the bottom bit is set) |
307 | | */ |
308 | 0 | r = BN_check_prime(p, ctx, cb); |
309 | | /* A.1.1.2 Step (11.8) : Return if p is prime */ |
310 | 0 | if (r > 0) { |
311 | 0 | *counter = i; |
312 | 0 | ret = 1; /* return success */ |
313 | 0 | goto err; |
314 | 0 | } |
315 | 0 | if (r != 0) |
316 | 0 | goto err; |
317 | 0 | } |
318 | | /* Step (11.9) : offset = offset + n + 1 is done auto-magically */ |
319 | 0 | } |
320 | | /* No prime P found */ |
321 | 0 | ret = 0; |
322 | 0 | *res |= FFC_CHECK_P_NOT_PRIME; |
323 | 0 | err: |
324 | 0 | BN_CTX_end(ctx); |
325 | 0 | return ret; |
326 | 0 | } |
327 | | |
328 | | static int generate_q_fips186_4(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd, |
329 | | int qsize, unsigned char *seed, size_t seedlen, |
330 | | int generate_seed, int *retm, int *res, |
331 | | BN_GENCB *cb) |
332 | 0 | { |
333 | 0 | int ret = 0, r; |
334 | 0 | int m = *retm; |
335 | 0 | unsigned char md[EVP_MAX_MD_SIZE]; |
336 | 0 | int mdsize = EVP_MD_get_size(evpmd); |
337 | 0 | unsigned char *pmd; |
338 | 0 | OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx); |
339 | |
|
340 | 0 | if (mdsize <= 0) |
341 | 0 | goto err; |
342 | | |
343 | | /* find q */ |
344 | 0 | for (;;) { |
345 | 0 | if (!BN_GENCB_call(cb, 0, m++)) |
346 | 0 | goto err; |
347 | | |
348 | | /* A.1.1.2 Step (5) : generate seed with size seed_len */ |
349 | 0 | if (generate_seed |
350 | 0 | && RAND_bytes_ex(libctx, seed, seedlen, 0) <= 0) |
351 | 0 | goto err; |
352 | | /* |
353 | | * A.1.1.2 Step (6) AND |
354 | | * A.1.1.3 Step (7) |
355 | | * U = Hash(seed) % (2^(N-1)) |
356 | | */ |
357 | 0 | if (!EVP_Digest(seed, seedlen, md, NULL, evpmd, NULL)) |
358 | 0 | goto err; |
359 | | /* Take least significant bits of md */ |
360 | 0 | if (mdsize > qsize) |
361 | 0 | pmd = md + mdsize - qsize; |
362 | 0 | else |
363 | 0 | pmd = md; |
364 | 0 | if (mdsize < qsize) |
365 | 0 | memset(md + mdsize, 0, qsize - mdsize); |
366 | | |
367 | | /* |
368 | | * A.1.1.2 Step (7) AND |
369 | | * A.1.1.3 Step (8) |
370 | | * q = U + 2^(N-1) + (1 - U %2) (This sets top and bottom bits) |
371 | | */ |
372 | 0 | pmd[0] |= 0x80; |
373 | 0 | pmd[qsize - 1] |= 0x01; |
374 | 0 | if (!BN_bin2bn(pmd, qsize, q)) |
375 | 0 | goto err; |
376 | | |
377 | | /* |
378 | | * A.1.1.2 Step (8) AND |
379 | | * A.1.1.3 Step (9) |
380 | | * Test if q is prime |
381 | | */ |
382 | 0 | r = BN_check_prime(q, ctx, cb); |
383 | 0 | if (r > 0) { |
384 | 0 | ret = 1; |
385 | 0 | goto err; |
386 | 0 | } |
387 | | /* |
388 | | * A.1.1.3 Step (9) : If the provided seed didn't produce a prime q |
389 | | * return an error. |
390 | | */ |
391 | 0 | if (!generate_seed) { |
392 | 0 | *res |= FFC_CHECK_Q_NOT_PRIME; |
393 | 0 | goto err; |
394 | 0 | } |
395 | 0 | if (r != 0) |
396 | 0 | goto err; |
397 | | /* A.1.1.2 Step (9) : if q is not prime, try another q */ |
398 | 0 | } |
399 | 0 | err: |
400 | 0 | *retm = m; |
401 | 0 | return ret; |
402 | 0 | } |
403 | | |
404 | | static int generate_q_fips186_2(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd, |
405 | | unsigned char *buf, unsigned char *seed, |
406 | | size_t qsize, int generate_seed, int *retm, |
407 | | int *res, BN_GENCB *cb) |
408 | 0 | { |
409 | 0 | unsigned char buf2[EVP_MAX_MD_SIZE]; |
410 | 0 | unsigned char md[EVP_MAX_MD_SIZE]; |
411 | 0 | int i, r, ret = 0, m = *retm; |
412 | 0 | OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx); |
413 | | |
414 | | /* find q */ |
415 | 0 | for (;;) { |
416 | | /* step 1 */ |
417 | 0 | if (!BN_GENCB_call(cb, 0, m++)) |
418 | 0 | goto err; |
419 | | |
420 | 0 | if (generate_seed && RAND_bytes_ex(libctx, seed, qsize, 0) <= 0) |
421 | 0 | goto err; |
422 | | |
423 | 0 | memcpy(buf, seed, qsize); |
424 | 0 | memcpy(buf2, seed, qsize); |
425 | | |
426 | | /* precompute "SEED + 1" for step 7: */ |
427 | 0 | for (i = (int)qsize - 1; i >= 0; i--) { |
428 | 0 | buf[i]++; |
429 | 0 | if (buf[i] != 0) |
430 | 0 | break; |
431 | 0 | } |
432 | | |
433 | | /* step 2 */ |
434 | 0 | if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL)) |
435 | 0 | goto err; |
436 | 0 | if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) |
437 | 0 | goto err; |
438 | 0 | for (i = 0; i < (int)qsize; i++) |
439 | 0 | md[i] ^= buf2[i]; |
440 | | |
441 | | /* step 3 */ |
442 | 0 | md[0] |= 0x80; |
443 | 0 | md[qsize - 1] |= 0x01; |
444 | 0 | if (!BN_bin2bn(md, (int)qsize, q)) |
445 | 0 | goto err; |
446 | | |
447 | | /* step 4 */ |
448 | 0 | r = BN_check_prime(q, ctx, cb); |
449 | 0 | if (r > 0) { |
450 | | /* Found a prime */ |
451 | 0 | ret = 1; |
452 | 0 | goto err; |
453 | 0 | } |
454 | 0 | if (r != 0) |
455 | 0 | goto err; /* Exit if error */ |
456 | | /* Try another iteration if it wasn't prime - was in old code.. */ |
457 | 0 | generate_seed = 1; |
458 | 0 | } |
459 | 0 | err: |
460 | 0 | *retm = m; |
461 | 0 | return ret; |
462 | 0 | } |
463 | | |
464 | | static const char *default_mdname(size_t N) |
465 | 0 | { |
466 | 0 | if (N == 160) |
467 | 0 | return "SHA1"; |
468 | 0 | else if (N == 224) |
469 | 0 | return "SHA-224"; |
470 | 0 | else if (N == 256) |
471 | 0 | return "SHA-256"; |
472 | 0 | return NULL; |
473 | 0 | } |
474 | | |
475 | | /* |
476 | | * FIPS 186-4 FFC parameter generation (as defined in Appendix A). |
477 | | * The same code is used for validation (when validate_flags != 0) |
478 | | * |
479 | | * The primes p & q are generated/validated using: |
480 | | * A.1.1.2 Generation of probable primes p & q using approved hash. |
481 | | * A.1.1.3 Validation of generated probable primes |
482 | | * |
483 | | * Generator 'g' has 2 types in FIPS 186-4: |
484 | | * (1) A.2.1 unverifiable generation of generator g. |
485 | | * A.2.2 Assurance of the validity of unverifiable generator g. |
486 | | * (2) A.2.3 Verifiable Canonical Generation of the generator g. |
487 | | * A.2.4 Validation for Canonical Generation of the generator g. |
488 | | * |
489 | | * Notes: |
490 | | * (1) is only a partial validation of g, The validation of (2) requires |
491 | | * the seed and index used during generation as input. |
492 | | * |
493 | | * params: used to pass in values for generation and validation. |
494 | | * params->md: is the digest to use, If this value is NULL, then the digest is |
495 | | * chosen using the value of N. |
496 | | * params->flags: |
497 | | * For validation one of: |
498 | | * -FFC_PARAM_FLAG_VALIDATE_PQ |
499 | | * -FFC_PARAM_FLAG_VALIDATE_G |
500 | | * -FFC_PARAM_FLAG_VALIDATE_PQG |
501 | | * For generation of p & q: |
502 | | * - This is skipped if p & q are passed in. |
503 | | * - If the seed is passed in then generation of p & q uses this seed (and if |
504 | | * this fails an error will occur). |
505 | | * - Otherwise the seed is generated, and values of p & q are generated and |
506 | | * the value of seed and counter are optionally returned. |
507 | | * For the generation of g (after the generation of p, q): |
508 | | * - If the seed has been generated or passed in and a valid gindex is passed |
509 | | * in then canonical generation of g is used otherwise unverifiable |
510 | | * generation of g is chosen. |
511 | | * For validation of p & q: |
512 | | * - p, q, and the seed and counter used for generation must be passed in. |
513 | | * For validation of g: |
514 | | * - For a partial validation : p, q and g are required. |
515 | | * - For a canonical validation : the gindex and seed used for generation are |
516 | | * also required. |
517 | | * mode: The mode - either FFC_PARAM_MODE_GENERATE or FFC_PARAM_MODE_VERIFY. |
518 | | * type: The key type - FFC_PARAM_TYPE_DSA or FFC_PARAM_TYPE_DH. |
519 | | * L: is the size of the prime p in bits (e.g 2048) |
520 | | * N: is the size of the prime q in bits (e.g 256) |
521 | | * res: A returned failure reason (One of FFC_CHECK_XXXX), |
522 | | * or 0 for general failures. |
523 | | * cb: A callback (can be NULL) that is called during different phases |
524 | | * |
525 | | * Returns: |
526 | | * - FFC_PARAM_RET_STATUS_FAILED: if there was an error, or validation failed. |
527 | | * - FFC_PARAM_RET_STATUS_SUCCESS if the generation or validation succeeded. |
528 | | * - FFC_PARAM_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded, |
529 | | * but G is unverifiable. |
530 | | */ |
531 | | int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, |
532 | | FFC_PARAMS *params, int mode, int type, |
533 | | size_t L, size_t N, int *res, |
534 | | BN_GENCB *cb) |
535 | 0 | { |
536 | 0 | int ok = FFC_PARAM_RET_STATUS_FAILED; |
537 | 0 | unsigned char *seed = NULL, *seed_tmp = NULL; |
538 | 0 | int mdsize, counter = 0, pcounter = 0, r = 0; |
539 | 0 | size_t seedlen = 0; |
540 | 0 | BIGNUM *tmp, *pm1, *e, *test; |
541 | 0 | BIGNUM *g = NULL, *q = NULL, *p = NULL; |
542 | 0 | BN_MONT_CTX *mont = NULL; |
543 | 0 | int n = 0, m = 0, qsize; |
544 | 0 | int canonical_g = 0, hret = 0; |
545 | 0 | BN_CTX *ctx = NULL; |
546 | 0 | EVP_MD_CTX *mctx = NULL; |
547 | 0 | EVP_MD *md = NULL; |
548 | 0 | int verify = (mode == FFC_PARAM_MODE_VERIFY); |
549 | 0 | unsigned int flags = verify ? params->flags : 0; |
550 | 0 | const char *def_name; |
551 | |
|
552 | 0 | *res = 0; |
553 | |
|
554 | 0 | if (params->mdname != NULL) { |
555 | 0 | md = EVP_MD_fetch(libctx, params->mdname, params->mdprops); |
556 | 0 | } else { |
557 | 0 | if (N == 0) |
558 | 0 | N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8; |
559 | 0 | def_name = default_mdname(N); |
560 | 0 | if (def_name == NULL) { |
561 | 0 | *res = FFC_CHECK_INVALID_Q_VALUE; |
562 | 0 | goto err; |
563 | 0 | } |
564 | 0 | md = EVP_MD_fetch(libctx, def_name, params->mdprops); |
565 | 0 | } |
566 | 0 | if (md == NULL) |
567 | 0 | goto err; |
568 | 0 | mdsize = EVP_MD_get_size(md); |
569 | 0 | if (mdsize <= 0) |
570 | 0 | goto err; |
571 | | |
572 | 0 | if (N == 0) |
573 | 0 | N = mdsize * 8; |
574 | 0 | qsize = (int)(N >> 3); |
575 | | |
576 | | /* |
577 | | * A.1.1.2 Step (1) AND |
578 | | * A.1.1.3 Step (3) |
579 | | * Check that the L,N pair is an acceptable pair. |
580 | | */ |
581 | 0 | if (L <= N || !ffc_validate_LN(L, N, type, verify)) { |
582 | 0 | *res = FFC_CHECK_BAD_LN_PAIR; |
583 | 0 | goto err; |
584 | 0 | } |
585 | | |
586 | 0 | mctx = EVP_MD_CTX_new(); |
587 | 0 | if (mctx == NULL) |
588 | 0 | goto err; |
589 | | |
590 | 0 | if ((ctx = BN_CTX_new_ex(libctx)) == NULL) |
591 | 0 | goto err; |
592 | | |
593 | 0 | BN_CTX_start(ctx); |
594 | 0 | g = BN_CTX_get(ctx); |
595 | 0 | pm1 = BN_CTX_get(ctx); |
596 | 0 | e = BN_CTX_get(ctx); |
597 | 0 | test = BN_CTX_get(ctx); |
598 | 0 | tmp = BN_CTX_get(ctx); |
599 | 0 | if (tmp == NULL) |
600 | 0 | goto err; |
601 | | |
602 | 0 | seedlen = params->seedlen; |
603 | 0 | if (seedlen == 0) |
604 | 0 | seedlen = (size_t)mdsize; |
605 | | /* If the seed was passed in - use this value as the seed */ |
606 | 0 | if (params->seed != NULL) |
607 | 0 | seed = params->seed; |
608 | |
|
609 | 0 | if (!verify) { |
610 | | /* For generation: p & q must both be NULL or NON-NULL */ |
611 | 0 | if ((params->p == NULL) != (params->q == NULL)) { |
612 | 0 | *res = FFC_CHECK_INVALID_PQ; |
613 | 0 | goto err; |
614 | 0 | } |
615 | 0 | } else { |
616 | | /* Validation of p,q requires seed and counter to be valid */ |
617 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) { |
618 | 0 | if (seed == NULL || params->pcounter < 0) { |
619 | 0 | *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; |
620 | 0 | goto err; |
621 | 0 | } |
622 | 0 | } |
623 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) { |
624 | | /* validation of g also requires g to be set */ |
625 | 0 | if (params->g == NULL) { |
626 | 0 | *res = FFC_CHECK_INVALID_G; |
627 | 0 | goto err; |
628 | 0 | } |
629 | 0 | } |
630 | 0 | } |
631 | | |
632 | | /* |
633 | | * If p & q are passed in and |
634 | | * validate_flags = 0 then skip the generation of PQ. |
635 | | * validate_flags = VALIDATE_G then also skip the validation of PQ. |
636 | | */ |
637 | 0 | if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) { |
638 | | /* p and q already exists so only generate g */ |
639 | 0 | p = params->p; |
640 | 0 | q = params->q; |
641 | 0 | goto g_only; |
642 | | /* otherwise fall through to validate p & q */ |
643 | 0 | } |
644 | | |
645 | | /* p & q will be used for generation and validation */ |
646 | 0 | p = BN_CTX_get(ctx); |
647 | 0 | q = BN_CTX_get(ctx); |
648 | 0 | if (q == NULL) |
649 | 0 | goto err; |
650 | | |
651 | | /* |
652 | | * A.1.1.2 Step (2) AND |
653 | | * A.1.1.3 Step (6) |
654 | | * Return invalid if seedlen < N |
655 | | */ |
656 | 0 | if ((seedlen * 8) < N) { |
657 | 0 | *res = FFC_CHECK_INVALID_SEED_SIZE; |
658 | 0 | goto err; |
659 | 0 | } |
660 | | |
661 | 0 | seed_tmp = OPENSSL_malloc(seedlen); |
662 | 0 | if (seed_tmp == NULL) |
663 | 0 | goto err; |
664 | | |
665 | 0 | if (seed == NULL) { |
666 | | /* Validation requires the seed to be supplied */ |
667 | 0 | if (verify) { |
668 | 0 | *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; |
669 | 0 | goto err; |
670 | 0 | } |
671 | | /* if the seed is not supplied then alloc a seed buffer */ |
672 | 0 | seed = OPENSSL_malloc(seedlen); |
673 | 0 | if (seed == NULL) |
674 | 0 | goto err; |
675 | 0 | } |
676 | | |
677 | | /* A.1.1.2 Step (11): max loop count = 4L - 1 */ |
678 | 0 | counter = (int)(4 * L - 1); |
679 | | /* Validation requires the counter to be supplied */ |
680 | 0 | if (verify) { |
681 | | /* A.1.1.3 Step (4) : if (counter > (4L -1)) return INVALID */ |
682 | 0 | if (params->pcounter > counter) { |
683 | 0 | *res = FFC_CHECK_INVALID_COUNTER; |
684 | 0 | goto err; |
685 | 0 | } |
686 | 0 | counter = params->pcounter; |
687 | 0 | } |
688 | | |
689 | | /* |
690 | | * A.1.1.2 Step (3) AND |
691 | | * A.1.1.3 Step (10) |
692 | | * n = floor(L / hash_outlen) - 1 |
693 | | */ |
694 | 0 | n = (int)((L - 1) / (mdsize << 3)); |
695 | | |
696 | | /* Calculate 2^(L-1): Used in step A.1.1.2 Step (11.3) */ |
697 | 0 | if (!BN_lshift(test, BN_value_one(), (int)(L - 1))) |
698 | 0 | goto err; |
699 | | |
700 | 0 | for (;;) { |
701 | 0 | if (!generate_q_fips186_4(ctx, q, md, qsize, seed, seedlen, |
702 | 0 | seed != params->seed, &m, res, cb)) |
703 | 0 | goto err; |
704 | | /* A.1.1.3 Step (9): Verify that q matches the expected value */ |
705 | 0 | if (verify && (BN_cmp(q, params->q) != 0)) { |
706 | 0 | *res = FFC_CHECK_Q_MISMATCH; |
707 | 0 | goto err; |
708 | 0 | } |
709 | 0 | if (!BN_GENCB_call(cb, 2, 0)) |
710 | 0 | goto err; |
711 | 0 | if (!BN_GENCB_call(cb, 3, 0)) |
712 | 0 | goto err; |
713 | | |
714 | 0 | memcpy(seed_tmp, seed, seedlen); |
715 | 0 | r = generate_p(ctx, md, counter, n, seed_tmp, seedlen, q, p, (int)L, |
716 | 0 | cb, &pcounter, res); |
717 | 0 | if (r > 0) |
718 | 0 | break; /* found p */ |
719 | 0 | if (r < 0) |
720 | 0 | goto err; |
721 | | /* |
722 | | * A.1.1.3 Step (14): |
723 | | * If we get here we failed to get a p for the given seed. If the |
724 | | * seed is not random then it needs to fail (as it will always fail). |
725 | | */ |
726 | 0 | if (seed == params->seed) { |
727 | 0 | *res = FFC_CHECK_P_NOT_PRIME; |
728 | 0 | goto err; |
729 | 0 | } |
730 | 0 | } |
731 | 0 | if (!BN_GENCB_call(cb, 2, 1)) |
732 | 0 | goto err; |
733 | | /* |
734 | | * Gets here if we found p. |
735 | | * A.1.1.3 Step (14): return error if i != counter OR computed_p != known_p. |
736 | | */ |
737 | 0 | if (verify && (pcounter != counter || (BN_cmp(p, params->p) != 0))) |
738 | 0 | goto err; |
739 | | |
740 | | /* If validating p & q only then skip the g validation test */ |
741 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_PQG) == FFC_PARAM_FLAG_VALIDATE_PQ) |
742 | 0 | goto pass; |
743 | 0 | g_only: |
744 | 0 | if ((mont = BN_MONT_CTX_new()) == NULL) |
745 | 0 | goto err; |
746 | 0 | if (!BN_MONT_CTX_set(mont, p, ctx)) |
747 | 0 | goto err; |
748 | | |
749 | 0 | if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) |
750 | 0 | && !ossl_ffc_params_validate_unverifiable_g(ctx, mont, p, q, params->g, |
751 | 0 | tmp, res)) |
752 | 0 | goto err; |
753 | | |
754 | | /* |
755 | | * A.2.1 Step (1) AND |
756 | | * A.2.3 Step (3) AND |
757 | | * A.2.4 Step (5) |
758 | | * e = (p - 1) / q (i.e- Cofactor 'e' is given by p = q * e + 1) |
759 | | */ |
760 | 0 | if (!(BN_sub(pm1, p, BN_value_one()) && BN_div(e, NULL, pm1, q, ctx))) |
761 | 0 | goto err; |
762 | | |
763 | | /* Canonical g requires a seed and index to be set */ |
764 | 0 | if ((seed != NULL) && (params->gindex != FFC_UNVERIFIABLE_GINDEX)) { |
765 | 0 | canonical_g = 1; |
766 | 0 | if (!generate_canonical_g(ctx, mont, md, g, tmp, p, e, |
767 | 0 | params->gindex, seed, seedlen)) { |
768 | 0 | *res = FFC_CHECK_INVALID_G; |
769 | 0 | goto err; |
770 | 0 | } |
771 | | /* A.2.4 Step (13): Return valid if computed_g == g */ |
772 | 0 | if (verify && BN_cmp(g, params->g) != 0) { |
773 | 0 | *res = FFC_CHECK_G_MISMATCH; |
774 | 0 | goto err; |
775 | 0 | } |
776 | 0 | } else if (!verify) { |
777 | 0 | if (!generate_unverifiable_g(ctx, mont, g, tmp, p, e, pm1, &hret)) |
778 | 0 | goto err; |
779 | 0 | } |
780 | | |
781 | 0 | if (!BN_GENCB_call(cb, 3, 1)) |
782 | 0 | goto err; |
783 | | |
784 | 0 | if (!verify) { |
785 | 0 | if (p != params->p) { |
786 | 0 | BN_free(params->p); |
787 | 0 | params->p = BN_dup(p); |
788 | 0 | } |
789 | 0 | if (q != params->q) { |
790 | 0 | BN_free(params->q); |
791 | 0 | params->q = BN_dup(q); |
792 | 0 | } |
793 | 0 | if (g != params->g) { |
794 | 0 | BN_free(params->g); |
795 | 0 | params->g = BN_dup(g); |
796 | 0 | } |
797 | 0 | if (params->p == NULL || params->q == NULL || params->g == NULL) |
798 | 0 | goto err; |
799 | 0 | if (!ossl_ffc_params_set_validate_params(params, seed, seedlen, |
800 | 0 | pcounter)) |
801 | 0 | goto err; |
802 | 0 | params->h = hret; |
803 | 0 | } |
804 | 0 | pass: |
805 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0 && (canonical_g == 0)) |
806 | | /* Return for the case where g is partially valid */ |
807 | 0 | ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G; |
808 | 0 | else |
809 | 0 | ok = FFC_PARAM_RET_STATUS_SUCCESS; |
810 | 0 | err: |
811 | 0 | if (seed != params->seed) |
812 | 0 | OPENSSL_free(seed); |
813 | 0 | OPENSSL_free(seed_tmp); |
814 | 0 | if (ctx != NULL) |
815 | 0 | BN_CTX_end(ctx); |
816 | 0 | BN_CTX_free(ctx); |
817 | 0 | BN_MONT_CTX_free(mont); |
818 | 0 | EVP_MD_CTX_free(mctx); |
819 | 0 | EVP_MD_free(md); |
820 | 0 | return ok; |
821 | 0 | } |
822 | | |
823 | | /* Note this function is only used for verification in fips mode */ |
824 | | int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx, |
825 | | FFC_PARAMS *params, int mode, int type, |
826 | | size_t L, size_t N, int *res, |
827 | | BN_GENCB *cb) |
828 | 0 | { |
829 | 0 | int ok = FFC_PARAM_RET_STATUS_FAILED; |
830 | 0 | unsigned char seed[SHA256_DIGEST_LENGTH]; |
831 | 0 | unsigned char buf[SHA256_DIGEST_LENGTH]; |
832 | 0 | BIGNUM *r0, *test, *tmp, *g = NULL, *q = NULL, *p = NULL; |
833 | 0 | BN_MONT_CTX *mont = NULL; |
834 | 0 | EVP_MD *md = NULL; |
835 | 0 | int md_size; |
836 | 0 | size_t qsize; |
837 | 0 | int n = 0, m = 0; |
838 | 0 | int counter = 0, pcounter = 0, use_random_seed; |
839 | 0 | int rv; |
840 | 0 | BN_CTX *ctx = NULL; |
841 | 0 | int hret = -1; |
842 | 0 | unsigned char *seed_in = params->seed; |
843 | 0 | size_t seed_len = params->seedlen; |
844 | 0 | int verify = (mode == FFC_PARAM_MODE_VERIFY); |
845 | 0 | unsigned int flags = verify ? params->flags : 0; |
846 | 0 | const char *def_name; |
847 | |
|
848 | 0 | *res = 0; |
849 | |
|
850 | 0 | if (params->mdname != NULL) { |
851 | 0 | md = EVP_MD_fetch(libctx, params->mdname, params->mdprops); |
852 | 0 | } else { |
853 | 0 | if (N == 0) |
854 | 0 | N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8; |
855 | 0 | def_name = default_mdname(N); |
856 | 0 | if (def_name == NULL) { |
857 | 0 | *res = FFC_CHECK_INVALID_Q_VALUE; |
858 | 0 | goto err; |
859 | 0 | } |
860 | 0 | md = EVP_MD_fetch(libctx, def_name, params->mdprops); |
861 | 0 | } |
862 | 0 | if (md == NULL) |
863 | 0 | goto err; |
864 | 0 | md_size = EVP_MD_get_size(md); |
865 | 0 | if (md_size <= 0) |
866 | 0 | goto err; |
867 | 0 | if (N == 0) |
868 | 0 | N = md_size * 8; |
869 | 0 | qsize = N >> 3; |
870 | | |
871 | | /* |
872 | | * The original spec allowed L = 512 + 64*j (j = 0.. 8) |
873 | | * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf |
874 | | * says that 512 can be used for legacy verification. |
875 | | */ |
876 | 0 | if (L < 512) { |
877 | 0 | *res = FFC_CHECK_BAD_LN_PAIR; |
878 | 0 | goto err; |
879 | 0 | } |
880 | 0 | if (qsize != SHA_DIGEST_LENGTH |
881 | 0 | && qsize != SHA224_DIGEST_LENGTH |
882 | 0 | && qsize != SHA256_DIGEST_LENGTH) { |
883 | | /* invalid q size */ |
884 | 0 | *res = FFC_CHECK_INVALID_Q_VALUE; |
885 | 0 | goto err; |
886 | 0 | } |
887 | | |
888 | 0 | L = (L + 63) / 64 * 64; |
889 | |
|
890 | 0 | if (seed_in != NULL) { |
891 | 0 | if (seed_len < qsize) { |
892 | 0 | *res = FFC_CHECK_INVALID_SEED_SIZE; |
893 | 0 | goto err; |
894 | 0 | } |
895 | | /* Only consume as much seed as is expected. */ |
896 | 0 | if (seed_len > qsize) |
897 | 0 | seed_len = qsize; |
898 | 0 | memcpy(seed, seed_in, seed_len); |
899 | 0 | } |
900 | | |
901 | 0 | ctx = BN_CTX_new_ex(libctx); |
902 | 0 | if (ctx == NULL) |
903 | 0 | goto err; |
904 | | |
905 | 0 | BN_CTX_start(ctx); |
906 | |
|
907 | 0 | r0 = BN_CTX_get(ctx); |
908 | 0 | g = BN_CTX_get(ctx); |
909 | 0 | q = BN_CTX_get(ctx); |
910 | 0 | p = BN_CTX_get(ctx); |
911 | 0 | tmp = BN_CTX_get(ctx); |
912 | 0 | test = BN_CTX_get(ctx); |
913 | 0 | if (test == NULL) |
914 | 0 | goto err; |
915 | | |
916 | 0 | if (!BN_lshift(test, BN_value_one(), (int)(L - 1))) |
917 | 0 | goto err; |
918 | | |
919 | 0 | if (!verify) { |
920 | | /* For generation: p & q must both be NULL or NON-NULL */ |
921 | 0 | if ((params->p != NULL) != (params->q != NULL)) { |
922 | 0 | *res = FFC_CHECK_INVALID_PQ; |
923 | 0 | goto err; |
924 | 0 | } |
925 | 0 | } else { |
926 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) { |
927 | | /* Validation of p,q requires seed and counter to be valid */ |
928 | 0 | if (seed_in == NULL || params->pcounter < 0) { |
929 | 0 | *res = FFC_CHECK_MISSING_SEED_OR_COUNTER; |
930 | 0 | goto err; |
931 | 0 | } |
932 | 0 | } |
933 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) { |
934 | | /* validation of g also requires g to be set */ |
935 | 0 | if (params->g == NULL) { |
936 | 0 | *res = FFC_CHECK_INVALID_G; |
937 | 0 | goto err; |
938 | 0 | } |
939 | 0 | } |
940 | 0 | } |
941 | | |
942 | 0 | if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) { |
943 | | /* p and q already exists so only generate g */ |
944 | 0 | p = params->p; |
945 | 0 | q = params->q; |
946 | 0 | goto g_only; |
947 | | /* otherwise fall through to validate p and q */ |
948 | 0 | } |
949 | | |
950 | 0 | use_random_seed = (seed_in == NULL); |
951 | 0 | for (;;) { |
952 | 0 | if (!generate_q_fips186_2(ctx, q, md, buf, seed, qsize, |
953 | 0 | use_random_seed, &m, res, cb)) |
954 | 0 | goto err; |
955 | | |
956 | 0 | if (!BN_GENCB_call(cb, 2, 0)) |
957 | 0 | goto err; |
958 | 0 | if (!BN_GENCB_call(cb, 3, 0)) |
959 | 0 | goto err; |
960 | | |
961 | | /* step 6 */ |
962 | 0 | n = (int)((L - 1) / 160); |
963 | 0 | counter = (int)(4 * L - 1); /* Was 4096 */ |
964 | | /* Validation requires the counter to be supplied */ |
965 | 0 | if (verify) { |
966 | 0 | if (params->pcounter > counter) { |
967 | 0 | *res = FFC_CHECK_INVALID_COUNTER; |
968 | 0 | goto err; |
969 | 0 | } |
970 | 0 | counter = params->pcounter; |
971 | 0 | } |
972 | | |
973 | 0 | rv = generate_p(ctx, md, counter, n, buf, qsize, q, p, (int)L, cb, |
974 | 0 | &pcounter, res); |
975 | 0 | if (rv > 0) |
976 | 0 | break; /* found it */ |
977 | 0 | if (rv == -1) |
978 | 0 | goto err; |
979 | | /* This is what the old code did - probably not a good idea! */ |
980 | 0 | use_random_seed = 1; |
981 | 0 | } |
982 | | |
983 | 0 | if (!BN_GENCB_call(cb, 2, 1)) |
984 | 0 | goto err; |
985 | | |
986 | 0 | if (verify) { |
987 | 0 | if (pcounter != counter) { |
988 | 0 | *res = FFC_CHECK_COUNTER_MISMATCH; |
989 | 0 | goto err; |
990 | 0 | } |
991 | 0 | if (BN_cmp(p, params->p) != 0) { |
992 | 0 | *res = FFC_CHECK_P_MISMATCH; |
993 | 0 | goto err; |
994 | 0 | } |
995 | 0 | } |
996 | | /* If validating p & q only then skip the g validation test */ |
997 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_PQG) == FFC_PARAM_FLAG_VALIDATE_PQ) |
998 | 0 | goto pass; |
999 | 0 | g_only: |
1000 | 0 | if ((mont = BN_MONT_CTX_new()) == NULL) |
1001 | 0 | goto err; |
1002 | 0 | if (!BN_MONT_CTX_set(mont, p, ctx)) |
1003 | 0 | goto err; |
1004 | | |
1005 | 0 | if (!verify) { |
1006 | | /* We now need to generate g */ |
1007 | | /* set test = p - 1 */ |
1008 | 0 | if (!BN_sub(test, p, BN_value_one())) |
1009 | 0 | goto err; |
1010 | | /* Set r0 = (p - 1) / q */ |
1011 | 0 | if (!BN_div(r0, NULL, test, q, ctx)) |
1012 | 0 | goto err; |
1013 | 0 | if (!generate_unverifiable_g(ctx, mont, g, tmp, p, r0, test, &hret)) |
1014 | 0 | goto err; |
1015 | 0 | } else if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) |
1016 | 0 | && !ossl_ffc_params_validate_unverifiable_g(ctx, mont, p, q, |
1017 | 0 | params->g, tmp, |
1018 | 0 | res)) { |
1019 | 0 | goto err; |
1020 | 0 | } |
1021 | | |
1022 | 0 | if (!BN_GENCB_call(cb, 3, 1)) |
1023 | 0 | goto err; |
1024 | | |
1025 | 0 | if (!verify) { |
1026 | 0 | if (p != params->p) { |
1027 | 0 | BN_free(params->p); |
1028 | 0 | params->p = BN_dup(p); |
1029 | 0 | } |
1030 | 0 | if (q != params->q) { |
1031 | 0 | BN_free(params->q); |
1032 | 0 | params->q = BN_dup(q); |
1033 | 0 | } |
1034 | 0 | if (g != params->g) { |
1035 | 0 | BN_free(params->g); |
1036 | 0 | params->g = BN_dup(g); |
1037 | 0 | } |
1038 | 0 | if (params->p == NULL || params->q == NULL || params->g == NULL) |
1039 | 0 | goto err; |
1040 | 0 | if (!ossl_ffc_params_set_validate_params(params, seed, qsize, pcounter)) |
1041 | 0 | goto err; |
1042 | 0 | params->h = hret; |
1043 | 0 | } |
1044 | 0 | pass: |
1045 | 0 | if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) |
1046 | 0 | ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G; |
1047 | 0 | else |
1048 | 0 | ok = FFC_PARAM_RET_STATUS_SUCCESS; |
1049 | 0 | err: |
1050 | 0 | if (ctx != NULL) |
1051 | 0 | BN_CTX_end(ctx); |
1052 | 0 | BN_CTX_free(ctx); |
1053 | 0 | BN_MONT_CTX_free(mont); |
1054 | 0 | EVP_MD_free(md); |
1055 | 0 | return ok; |
1056 | 0 | } |
1057 | | |
1058 | | int ossl_ffc_params_FIPS186_4_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params, |
1059 | | int type, size_t L, size_t N, |
1060 | | int *res, BN_GENCB *cb) |
1061 | 0 | { |
1062 | 0 | return ossl_ffc_params_FIPS186_4_gen_verify(libctx, params, |
1063 | 0 | FFC_PARAM_MODE_GENERATE, |
1064 | 0 | type, L, N, res, cb); |
1065 | 0 | } |
1066 | | |
1067 | | /* This should no longer be used in FIPS mode */ |
1068 | | int ossl_ffc_params_FIPS186_2_generate(OSSL_LIB_CTX *libctx, FFC_PARAMS *params, |
1069 | | int type, size_t L, size_t N, |
1070 | | int *res, BN_GENCB *cb) |
1071 | 0 | { |
1072 | 0 | if (!ossl_ffc_params_FIPS186_2_gen_verify(libctx, params, |
1073 | 0 | FFC_PARAM_MODE_GENERATE, |
1074 | 0 | type, L, N, res, cb)) |
1075 | 0 | return 0; |
1076 | | |
1077 | 0 | ossl_ffc_params_enable_flags(params, FFC_PARAM_FLAG_VALIDATE_LEGACY, 1); |
1078 | 0 | return 1; |
1079 | 0 | } |