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