70f083603f4575a4bb6800c5b3af82694cd27466
[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
15 /*-
16  * Check that p and g are suitable enough
17  *
18  * p is odd
19  * 1 < g < p - 1
20  */
21 int DH_check_params_ex(const DH *dh)
22 {
23     int errflags = 0;
24
25     if (!DH_check_params(dh, &errflags))
26         return 0;
27
28     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
29         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
30     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
31         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
32     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
33         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_SMALL);
34     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
35         DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_LARGE);
36
37     return errflags == 0;
38 }
39
40 int DH_check_params(const DH *dh, int *ret)
41 {
42     int ok = 0;
43     BIGNUM *tmp = NULL;
44     BN_CTX *ctx = NULL;
45
46     *ret = 0;
47     ctx = BN_CTX_new();
48     if (ctx == NULL)
49         goto err;
50     BN_CTX_start(ctx);
51     tmp = BN_CTX_get(ctx);
52     if (tmp == NULL)
53         goto err;
54
55     if (!BN_is_odd(dh->p))
56         *ret |= DH_CHECK_P_NOT_PRIME;
57     if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g))
58         *ret |= DH_NOT_SUITABLE_GENERATOR;
59     if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
60         goto err;
61     if (BN_cmp(dh->g, tmp) >= 0)
62         *ret |= DH_NOT_SUITABLE_GENERATOR;
63     if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS)
64         *ret |= DH_MODULUS_TOO_SMALL;
65     if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS)
66         *ret |= DH_MODULUS_TOO_LARGE;
67
68     ok = 1;
69  err:
70     BN_CTX_end(ctx);
71     BN_CTX_free(ctx);
72     return ok;
73 }
74
75 /*-
76  * Check that p is a safe prime and
77  * g is a suitable generator.
78  */
79 int DH_check_ex(const DH *dh)
80 {
81     int errflags = 0;
82
83     if (!DH_check(dh, &errflags))
84         return 0;
85
86     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
87         DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
88     if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
89         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
90     if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
91         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
92     if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
93         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
94     if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
95         DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
96     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
97         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
98     if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
99         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
100     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
101         DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_SMALL);
102     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
103         DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_LARGE);
104
105     return errflags == 0;
106 }
107
108 int DH_check(const DH *dh, int *ret)
109 {
110     int ok = 0, r;
111     BN_CTX *ctx = NULL;
112     BIGNUM *t1 = NULL, *t2 = NULL;
113
114     if (!DH_check_params(dh, ret))
115         return 0;
116
117     ctx = BN_CTX_new();
118     if (ctx == NULL)
119         goto err;
120     BN_CTX_start(ctx);
121     t1 = BN_CTX_get(ctx);
122     t2 = BN_CTX_get(ctx);
123     if (t2 == NULL)
124         goto err;
125
126     if (dh->q) {
127         if (BN_cmp(dh->g, BN_value_one()) <= 0)
128             *ret |= DH_NOT_SUITABLE_GENERATOR;
129         else if (BN_cmp(dh->g, dh->p) >= 0)
130             *ret |= DH_NOT_SUITABLE_GENERATOR;
131         else {
132             /* Check g^q == 1 mod p */
133             if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
134                 goto err;
135             if (!BN_is_one(t1))
136                 *ret |= DH_NOT_SUITABLE_GENERATOR;
137         }
138         r = BN_check_prime(dh->q, ctx, NULL);
139         if (r < 0)
140             goto err;
141         if (!r)
142             *ret |= DH_CHECK_Q_NOT_PRIME;
143         /* Check p == 1 mod q  i.e. q divides p - 1 */
144         if (!BN_div(t1, t2, dh->p, dh->q, ctx))
145             goto err;
146         if (!BN_is_one(t2))
147             *ret |= DH_CHECK_INVALID_Q_VALUE;
148         if (dh->j && BN_cmp(dh->j, t1))
149             *ret |= DH_CHECK_INVALID_J_VALUE;
150     }
151
152     r = BN_check_prime(dh->p, ctx, NULL);
153     if (r < 0)
154         goto err;
155     if (!r)
156         *ret |= DH_CHECK_P_NOT_PRIME;
157     else if (!dh->q) {
158         if (!BN_rshift1(t1, dh->p))
159             goto err;
160         r = BN_check_prime(t1, ctx, NULL);
161         if (r < 0)
162             goto err;
163         if (!r)
164             *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
165     }
166     ok = 1;
167  err:
168     BN_CTX_end(ctx);
169     BN_CTX_free(ctx);
170     return ok;
171 }
172
173 int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
174 {
175     int errflags = 0;
176
177     if (!DH_check_pub_key(dh, pub_key, &errflags))
178         return 0;
179
180     if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
181         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
182     if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
183         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
184     if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
185         DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
186
187     return errflags == 0;
188 }
189
190 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
191 {
192     int ok = 0;
193     BIGNUM *tmp = NULL;
194     BN_CTX *ctx = NULL;
195
196     *ret = 0;
197     ctx = BN_CTX_new();
198     if (ctx == NULL)
199         goto err;
200     BN_CTX_start(ctx);
201     tmp = BN_CTX_get(ctx);
202     if (tmp == NULL || !BN_set_word(tmp, 1))
203         goto err;
204     if (BN_cmp(pub_key, tmp) <= 0)
205         *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
206     if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
207         goto err;
208     if (BN_cmp(pub_key, tmp) >= 0)
209         *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
210
211     if (dh->q != NULL) {
212         /* Check pub_key^q == 1 mod p */
213         if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
214             goto err;
215         if (!BN_is_one(tmp))
216             *ret |= DH_CHECK_PUBKEY_INVALID;
217     }
218
219     ok = 1;
220  err:
221     BN_CTX_end(ctx);
222     BN_CTX_free(ctx);
223     return ok;
224 }