/*
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* For the prime check..
* FIPS 186-4 Section C.3 Table C.1
* Returns the minimum number of Miller Rabin iterations for a L,N pair
* (where L = len(p), N = len(q))
* L N Min
* 1024 160 40
* 2048 224 56
* 2048 256 56
* 3072 256 64
*
* BN_check_prime() uses:
* 64 iterations for L <= 2048 OR
* 128 iterations for L > 2048
* So this satisfies the requirement.
*/
#include <string.h> /* memset */
#include <openssl/sha.h> /* SHA_DIGEST_LENGTH */
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/dherr.h>
#include <openssl/dsaerr.h>
#include "crypto/bn.h"
#include "internal/ffc.h"
/*
* Verify that the passed in L, N pair for DH or DSA is valid.
* Returns 0 if invalid, otherwise it returns the security strength.
*/
#ifdef FIPS_MODULE
static int ffc_validate_LN(size_t L, size_t N, int type, int verify)
{
if (type == FFC_PARAM_TYPE_DH) {
/* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */
if (L == 2048 && (N == 224 || N == 256))
return 112;
# ifndef OPENSSL_NO_DH
DHerr(0, DH_R_BAD_FFC_PARAMETERS);
# endif
} else if (type == FFC_PARAM_TYPE_DSA) {
/* Valid DSA L,N parameters from FIPS 186-4 Section 4.2 */
/* In fips mode 1024/160 can only be used for verification */
if (verify && L == 1024 && N == 160)
return 80;
if (L == 2048 && (N == 224 || N == 256))
return 112;
if (L == 3072 && N == 256)
return 128;
# ifndef OPENSSL_NO_DSA
DSAerr(0, DSA_R_BAD_FFC_PARAMETERS);
# endif
}
return 0;
}
#else
static int ffc_validate_LN(size_t L, size_t N, int type, int verify)
{
if (type == FFC_PARAM_TYPE_DH) {
/* Allow legacy 1024/160 in non fips mode */
if (L == 1024 && N == 160)
return 80;
/* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */
if (L == 2048 && (N == 224 || N == 256))
return 112;
# ifndef OPENSSL_NO_DH
DHerr(0, DH_R_BAD_FFC_PARAMETERS);
# endif
} else if (type == FFC_PARAM_TYPE_DSA) {
if (L == 1024 && N == 160)
return 80;
if (L == 2048 && (N == 224 || N == 256))
return 112;
if (L == 3072 && N == 256)
return 128;
# ifndef OPENSSL_NO_DSA
DSAerr(0, DSA_R_BAD_FFC_PARAMETERS);
# endif
}
return 0;
}
#endif /* FIPS_MODULE */
/* FIPS186-4 A.2.1 Unverifiable Generation of Generator g */
static int generate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, BIGNUM *g,
BIGNUM *hbn, const BIGNUM *p,
const BIGNUM *e,const BIGNUM *pm1,
int *hret)
{
int h = 2;
/* Step (2): choose h (where 1 < h)*/
if (!BN_set_word(hbn, h))
return 0;
for (;;) {
/* Step (3): g = h^e % p */
if (!BN_mod_exp_mont(g, hbn, e, p, ctx, mont))
return 0;
/* Step (4): Finish if g > 1 */
if (BN_cmp(g, BN_value_one()) > 0)
break;
/* Step (2) Choose any h in the range 1 < h < (p-1) */
if (!BN_add_word(hbn, 1) || BN_cmp(hbn, pm1) >= 0)
return