Coverage Report

Created: 2025-06-22 06:56

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