Add FFC param/key validation
[openssl.git] / crypto / dh / dh_check.c
1 /*
2  * Copyright 1995-2019 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 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/bn.h>
13 #include "dh_local.h"
14 #include "crypto/dh.h"
15
16 /*-
17  * Check that p and g are suitable enough
18  *
19  * p is odd
20  * 1 < g < p - 1
21  */
22 int DH_check_params_ex(const DH *dh)
23 {
24     int errflags = 0;
25
26     if (!DH_check_params(dh, &errflags))
27         return 0;
28
29     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
30         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
31     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
32         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
33     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
34         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_SMALL);
35     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
36         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_LARGE);
37
38     return errflags == 0;
39 }
40
41 #ifdef FIPS_MODE
42 int DH_check_params(const DH *dh, int *ret)
43 {
44     int nid;
45
46     *ret = 0;
47     /*
48      * SP800-56A R3 Section 5.5.2 Assurances of Domain Parameter Validity
49      * (1a) The domain parameters correspond to any approved safe prime group.
50      */
51     nid = DH_get_nid((DH *)dh);
52     if (nid != NID_undef)
53         return 1;
54     /*
55      * OR
56      * (2b) FFC domain params conform to FIPS-186-4 explicit domain param
57      * validity tests.
58      */
59     return ffc_params_FIPS186_4_validate(&dh->params, FFC_PARAM_TYPE_DH, NULL,
60                                          FFC_PARAMS_VALIDATE_ALL, ret, NULL);
61 }
62 #else
63 int DH_check_params(const DH *dh, int *ret)
64 {
65     int ok = 0;
66     BIGNUM *tmp = NULL;
67     BN_CTX *ctx = NULL;
68
69     *ret = 0;
70     ctx = BN_CTX_new();
71     if (ctx == NULL)
72         goto err;
73     BN_CTX_start(ctx);
74     tmp = BN_CTX_get(ctx);
75     if (tmp == NULL)
76         goto err;
77
78     if (!BN_is_odd(dh->params.p))
79         *ret |= DH_CHECK_P_NOT_PRIME;
80     if (BN_is_negative(dh->params.g)
81         || BN_is_zero(dh->params.g)
82         || BN_is_one(dh->params.g))
83         *ret |= DH_NOT_SUITABLE_GENERATOR;
84     if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1))
85         goto err;
86     if (BN_cmp(dh->params.g, tmp) >= 0)
87         *ret |= DH_NOT_SUITABLE_GENERATOR;
88     if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS)
89         *ret |= DH_MODULUS_TOO_SMALL;
90     if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS)
91         *ret |= DH_MODULUS_TOO_LARGE;
92
93     ok = 1;
94  err:
95     BN_CTX_end(ctx);
96     BN_CTX_free(ctx);
97     return ok;
98 }
99 #endif /* FIPS_MODE */
100
101 /*-
102  * Check that p is a safe prime and
103  * g is a suitable generator.
104  */
105 int DH_check_ex(const DH *dh)
106 {
107     int errflags = 0;
108
109     if (!DH_check(dh, &errflags))
110         return 0;
111
112     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
113         DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
114     if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
115         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
116     if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
117         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
118     if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
119         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
120     if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
121         DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
122     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
123         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
124     if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
125         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
126     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
127         DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_SMALL);
128     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
129         DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_LARGE);
130
131     return errflags == 0;
132 }
133
134 /* Note: according to documentation - this only checks the params */
135 int DH_check(const DH *dh, int *ret)
136 {
137 #ifdef FIPS_MODE
138     return DH_check_params(dh, ret);
139 #else
140     int ok = 0, r;
141     BN_CTX *ctx = NULL;
142     BIGNUM *t1 = NULL, *t2 = NULL;
143     int nid = DH_get_nid((DH *)dh);
144
145     *ret = 0;
146     if (nid != NID_undef)
147         return 1;
148
149     if (!DH_check_params(dh, ret))
150         return 0;
151
152     ctx = BN_CTX_new();
153     if (ctx == NULL)
154         goto err;
155     BN_CTX_start(ctx);
156     t1 = BN_CTX_get(ctx);
157     t2 = BN_CTX_get(ctx);
158     if (t2 == NULL)
159         goto err;
160
161     if (dh->params.q != NULL) {
162         if (BN_cmp(dh->params.g, BN_value_one()) <= 0)
163             *ret |= DH_NOT_SUITABLE_GENERATOR;
164         else if (BN_cmp(dh->params.g, dh->params.p) >= 0)
165             *ret |= DH_NOT_SUITABLE_GENERATOR;
166         else {
167             /* Check g^q == 1 mod p */
168             if (!BN_mod_exp(t1, dh->params.g, dh->params.q, dh->params.p, ctx))
169                 goto err;
170             if (!BN_is_one(t1))
171                 *ret |= DH_NOT_SUITABLE_GENERATOR;
172         }
173         r = BN_check_prime(dh->params.q, ctx, NULL);
174         if (r < 0)
175             goto err;
176         if (!r)
177             *ret |= DH_CHECK_Q_NOT_PRIME;
178         /* Check p == 1 mod q  i.e. q divides p - 1 */
179         if (!BN_div(t1, t2, dh->params.p, dh->params.q, ctx))
180             goto err;
181         if (!BN_is_one(t2))
182             *ret |= DH_CHECK_INVALID_Q_VALUE;
183         if (dh->params.j != NULL
184             && BN_cmp(dh->params.j, t1))
185             *ret |= DH_CHECK_INVALID_J_VALUE;
186     }
187
188     r = BN_check_prime(dh->params.p, ctx, NULL);
189     if (r < 0)
190         goto err;
191     if (!r)
192         *ret |= DH_CHECK_P_NOT_PRIME;
193     else if (dh->params.q == NULL) {
194         if (!BN_rshift1(t1, dh->params.p))
195             goto err;
196         r = BN_check_prime(t1, ctx, NULL);
197         if (r < 0)
198             goto err;
199         if (!r)
200             *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
201     }
202     ok = 1;
203  err:
204     BN_CTX_end(ctx);
205     BN_CTX_free(ctx);
206     return ok;
207 #endif /* FIPS_MODE */
208 }
209
210 int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
211 {
212     int errflags = 0;
213
214     if (!DH_check_pub_key(dh, pub_key, &errflags))
215         return 0;
216
217     if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
218         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
219     if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
220         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
221     if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
222         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
223
224     return errflags == 0;
225 }
226
227 /*
228  * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation.
229  */
230 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
231 {
232     return ffc_validate_public_key(&dh->params, pub_key, ret);
233 }
234
235 /*
236  * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation.
237  * To only be used with ephemeral FFC public keys generated using the approved
238  * safe-prime groups.
239  */
240 int dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret)
241 {
242     return ffc_validate_public_key_partial(&dh->params, pub_key, ret);
243 }
244
245 int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
246 {
247     int ok = 0;
248     BIGNUM *two_powN = NULL, *upper;
249
250     *ret = 0;
251     two_powN = BN_new();
252     if (two_powN == NULL)
253         return 0;
254     if (dh->params.q == NULL)
255         goto err;
256     upper = dh->params.q;
257
258     /* Is it from an approved Safe prime group ?*/
259     if (DH_get_nid((DH *)dh) != NID_undef) {
260         if (!BN_lshift(two_powN, BN_value_one(), dh->length))
261             goto err;
262         if (BN_cmp(two_powN, dh->params.q) < 0)
263             upper = two_powN;
264     }
265     if (!ffc_validate_private_key(upper, priv_key, ret))
266         goto err;
267
268     ok = 1;
269 err:
270     BN_free(two_powN);
271     return ok;
272 }
273
274 /*
275  * FFC pairwise check from SP800-56A R3.
276  *    Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
277  */
278 int dh_check_pairwise(DH *dh)
279 {
280     int ret = 0;
281     BN_CTX *ctx = NULL;
282     BIGNUM *pub_key = NULL;
283
284     if (dh->params.p == NULL
285         || dh->params.g == NULL
286         || dh->priv_key == NULL
287         || dh->pub_key == NULL)
288         return 0;
289
290     ctx = BN_CTX_new_ex(dh->libctx);
291     if (ctx == NULL)
292         goto err;
293     pub_key = BN_new();
294     if (pub_key == NULL)
295         goto err;
296
297     /* recalculate the public key = (g ^ priv) mod p */
298     if (!dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
299         goto err;
300     /* check it matches the existing pubic_key */
301     ret = BN_cmp(pub_key, dh->pub_key) == 0;
302 err:
303     BN_free(pub_key);
304     BN_CTX_free(ctx);
305     return ret;
306 }