1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/*
* Copyright 2019-2021 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
*/
/*
* Finite Field cryptography (FFC) is used for DSA and DH.
* This file contains methods for validation of FFC parameters.
* It calls the same functions as the generation as the code is very similar.
*/
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/dsaerr.h>
#include <openssl/dherr.h>
#include "internal/ffc.h"
/* FIPS186-4 A.2.2 Unverifiable partial validation of Generator g */
int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont,
const BIGNUM *p, const BIGNUM *q,
const BIGNUM *g, BIGNUM *tmp,
int *ret)
{
/*
* A.2.2 Step (1) AND
* A.2.4 Step (2)
* Verify that 2 <= g <= (p - 1)
*/
if (BN_cmp(g, BN_value_one()) <= 0 || BN_cmp(g, p) >= 0) {
*ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR;
return 0;
}
/*
* A.2.2 Step (2) AND
* A.2.4 Step (3)
* Check g^q mod p = 1
*/
if (!BN_mod_exp_mont(tmp, g, q, p, ctx, mont))
return 0;
if (BN_cmp(tmp, BN_value_one()) != 0) {
*ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR;
return 0;
}
return 1;
}
int ossl_ffc_params_FIPS186_4_validate(OSSL_LIB_CTX *libctx,
const FFC_PARAMS *params, int type,
int *res, BN_GENCB *cb)
{
size_t L, N;
if (params == NULL || params->p == NULL || params->q == NULL)
return FFC_PARAM_RET_STATUS_FAILED;
/* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */
L = BN_num_bits(params->p);
N = BN_num_bits(params->q);
return ossl_ffc_params_FIPS186_4_gen_verify(libctx, (FFC_PARAMS *)params,
FFC_PARAM_MODE_VERIFY, type,
L, N, res, cb);
}
/* This may be used in FIPS mode to validate deprecated FIPS-186-2 Params */
int ossl_ffc_params_FIPS186_2_validate(OSSL_LIB_CTX *libctx,
const FFC_PARAMS *params, int type,
int *res, BN_GENCB *cb)
{
size_t L, N;
if (params == NULL || params->p == NULL || params->q == NULL) {
*res = FFC_CHECK_INVALID_PQ;
return FFC_PARAM_RET_STATUS_FAILED;
}
/* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */
L = BN_num_bits(params->p);
N = BN_num_bits(params->q);
return ossl_ffc_params_FIPS186_2_gen_verify(libctx, (FFC_PARAMS *)params,
FFC_PARAM_MODE_VERIFY, type,
L, N, res, cb);
}
/*
* This does a simple check of L and N and partial g.
* It makes no attempt to do a full validation of p, q or g since these require
* extra parameters such as the digest and seed, which may not be available for
* this test.
*/
int ossl_ffc_params_simple_validate(OSSL_LIB_CTX *libctx, const FFC_PARAMS *params,
int paramstype, int *res)
{
int ret;
int tmpres = 0;
FFC_PARAMS tmpparams = {0};
if (params == NULL)
return 0;
if (res == NULL)
res = &tmpres;
if (!ossl_ffc_params_copy(&tmpparams, params))
return 0;
tmpparams.flags = FFC_PARAM_FLAG_VALIDATE_G;
tmpparams.gindex = FFC_UNVERIFIABLE_GINDEX;
#ifndef FIPS_MODULE
if (params->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY)
ret = ossl_ffc_params_FIPS186_2_validate(libctx, &tmpparams, paramstype,
res, NULL);
else
#endif
ret = ossl_ffc_params_FIPS186_4_validate(libctx, &tmpparams, paramstype,
res, NULL);
#ifndef OPENSSL_NO_DH
if (ret == FFC_PARAM_RET_STATUS_FAILED
&& (*res & FFC_ERROR_NOT_SUITABLE_GENERATOR) != 0) {
ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
}
#endif
ossl_ffc_params_cleanup(&tmpparams);
return ret != FFC_PARAM_RET_STATUS_FAILED;
}
/*
* If possible (or always in FIPS_MODULE) do full FIPS 186-4 validation.
* Otherwise do simple check but in addition also check the primality of the
* p and q.
*/
int ossl_ffc_params_full_validate(OSSL_LIB_CTX *libctx, const FFC_PARAMS *params,
int paramstype, int *res)
{
int tmpres = 0;
if (params == NULL)
return 0;
if (res == NULL)
res = &tmpres;
#ifdef FIPS_MODULE
return ossl_ffc_params_FIPS186_4_validate(libctx, params, paramstype,
res, NULL);
#else
if (params->seed != NULL) {
if (params->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY)
return ossl_ffc_params_FIPS186_2_validate(libctx, params, paramstype,
res, NULL);
else
return ossl_ffc_params_FIPS186_4_validate(libctx, params, paramstype,
res, NULL);
} else {
int ret = 0;
ret = ossl_ffc_params_simple_validate(libctx, params, paramstype, res);
if (ret) {
BN_CTX *ctx;
if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
return 0;
if (BN_check_prime(params->q, ctx, NULL) != 1) {
# ifndef OPENSSL_NO_DSA
ERR_raise(ERR_LIB_DSA, DSA_R_Q_NOT_PRIME);
# endif
ret = 0;
}
if (ret && BN_check_prime(params->p, ctx, NULL) != 1) {
# ifndef OPENSSL_NO_DSA
ERR_raise(ERR_LIB_DSA, DSA_R_P_NOT_PRIME);
# endif
ret = 0;
}
BN_CTX_free(ctx);
}
return ret;
}
#endif
}
|