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 | } |
225 | |