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