/src/openssl111/crypto/dh/dh_key.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the OpenSSL license (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 "dh_local.h" |
13 | | #include "crypto/bn.h" |
14 | | |
15 | | static int generate_key(DH *dh); |
16 | | static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); |
17 | | static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, |
18 | | const BIGNUM *a, const BIGNUM *p, |
19 | | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); |
20 | | static int dh_init(DH *dh); |
21 | | static int dh_finish(DH *dh); |
22 | | |
23 | | int DH_generate_key(DH *dh) |
24 | 0 | { |
25 | 0 | return dh->meth->generate_key(dh); |
26 | 0 | } |
27 | | |
28 | | /*- |
29 | | * NB: This function is inherently not constant time due to the |
30 | | * RFC 5246 (8.1.2) padding style that strips leading zero bytes. |
31 | | */ |
32 | | int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
33 | 0 | { |
34 | 0 | int ret = 0, i; |
35 | 0 | volatile size_t npad = 0, mask = 1; |
36 | | |
37 | | /* compute the key; ret is constant unless compute_key is external */ |
38 | 0 | if ((ret = dh->meth->compute_key(key, pub_key, dh)) <= 0) |
39 | 0 | return ret; |
40 | | |
41 | | /* count leading zero bytes, yet still touch all bytes */ |
42 | 0 | for (i = 0; i < ret; i++) { |
43 | 0 | mask &= !key[i]; |
44 | 0 | npad += mask; |
45 | 0 | } |
46 | | |
47 | | /* unpad key */ |
48 | 0 | ret -= npad; |
49 | | /* key-dependent memory access, potentially leaking npad / ret */ |
50 | 0 | memmove(key, key + npad, ret); |
51 | | /* key-dependent memory access, potentially leaking npad / ret */ |
52 | 0 | memset(key + ret, 0, npad); |
53 | |
|
54 | 0 | return ret; |
55 | 0 | } |
56 | | |
57 | | int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
58 | 0 | { |
59 | 0 | int rv, pad; |
60 | | |
61 | | /* rv is constant unless compute_key is external */ |
62 | 0 | rv = dh->meth->compute_key(key, pub_key, dh); |
63 | 0 | if (rv <= 0) |
64 | 0 | return rv; |
65 | 0 | pad = BN_num_bytes(dh->p) - rv; |
66 | | /* pad is constant (zero) unless compute_key is external */ |
67 | 0 | if (pad > 0) { |
68 | 0 | memmove(key + pad, key, rv); |
69 | 0 | memset(key, 0, pad); |
70 | 0 | } |
71 | 0 | return rv + pad; |
72 | 0 | } |
73 | | |
74 | | static DH_METHOD dh_ossl = { |
75 | | "OpenSSL DH Method", |
76 | | generate_key, |
77 | | compute_key, |
78 | | dh_bn_mod_exp, |
79 | | dh_init, |
80 | | dh_finish, |
81 | | DH_FLAG_FIPS_METHOD, |
82 | | NULL, |
83 | | NULL |
84 | | }; |
85 | | |
86 | | static const DH_METHOD *default_DH_method = &dh_ossl; |
87 | | |
88 | | const DH_METHOD *DH_OpenSSL(void) |
89 | 0 | { |
90 | 0 | return &dh_ossl; |
91 | 0 | } |
92 | | |
93 | | void DH_set_default_method(const DH_METHOD *meth) |
94 | 0 | { |
95 | 0 | default_DH_method = meth; |
96 | 0 | } |
97 | | |
98 | | const DH_METHOD *DH_get_default_method(void) |
99 | 0 | { |
100 | 0 | return default_DH_method; |
101 | 0 | } |
102 | | |
103 | | static int generate_key(DH *dh) |
104 | 0 | { |
105 | 0 | int ok = 0; |
106 | 0 | int generate_new_key = 0; |
107 | 0 | unsigned l; |
108 | 0 | BN_CTX *ctx = NULL; |
109 | 0 | BN_MONT_CTX *mont = NULL; |
110 | 0 | BIGNUM *pub_key = NULL, *priv_key = NULL; |
111 | |
|
112 | 0 | if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { |
113 | 0 | DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE); |
114 | 0 | return 0; |
115 | 0 | } |
116 | | |
117 | 0 | ctx = BN_CTX_new(); |
118 | 0 | if (ctx == NULL) |
119 | 0 | goto err; |
120 | | |
121 | 0 | if (dh->priv_key == NULL) { |
122 | 0 | priv_key = BN_secure_new(); |
123 | 0 | if (priv_key == NULL) |
124 | 0 | goto err; |
125 | 0 | generate_new_key = 1; |
126 | 0 | } else |
127 | 0 | priv_key = dh->priv_key; |
128 | | |
129 | 0 | if (dh->pub_key == NULL) { |
130 | 0 | pub_key = BN_new(); |
131 | 0 | if (pub_key == NULL) |
132 | 0 | goto err; |
133 | 0 | } else |
134 | 0 | pub_key = dh->pub_key; |
135 | | |
136 | 0 | if (dh->flags & DH_FLAG_CACHE_MONT_P) { |
137 | 0 | mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, |
138 | 0 | dh->lock, dh->p, ctx); |
139 | 0 | if (!mont) |
140 | 0 | goto err; |
141 | 0 | } |
142 | | |
143 | 0 | if (generate_new_key) { |
144 | 0 | if (dh->q) { |
145 | 0 | do { |
146 | 0 | if (!BN_priv_rand_range(priv_key, dh->q)) |
147 | 0 | goto err; |
148 | 0 | } |
149 | 0 | while (BN_is_zero(priv_key) || BN_is_one(priv_key)); |
150 | 0 | } else { |
151 | | /* secret exponent length */ |
152 | 0 | l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; |
153 | 0 | if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) |
154 | 0 | goto err; |
155 | | /* |
156 | | * We handle just one known case where g is a quadratic non-residue: |
157 | | * for g = 2: p % 8 == 3 |
158 | | */ |
159 | 0 | if (BN_is_word(dh->g, DH_GENERATOR_2) && !BN_is_bit_set(dh->p, 2)) { |
160 | | /* clear bit 0, since it won't be a secret anyway */ |
161 | 0 | if (!BN_clear_bit(priv_key, 0)) |
162 | 0 | goto err; |
163 | 0 | } |
164 | 0 | } |
165 | 0 | } |
166 | | |
167 | 0 | { |
168 | 0 | BIGNUM *prk = BN_new(); |
169 | |
|
170 | 0 | if (prk == NULL) |
171 | 0 | goto err; |
172 | 0 | BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); |
173 | |
|
174 | 0 | if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) { |
175 | 0 | BN_clear_free(prk); |
176 | 0 | goto err; |
177 | 0 | } |
178 | | /* We MUST free prk before any further use of priv_key */ |
179 | 0 | BN_clear_free(prk); |
180 | 0 | } |
181 | | |
182 | 0 | dh->pub_key = pub_key; |
183 | 0 | dh->priv_key = priv_key; |
184 | 0 | ok = 1; |
185 | 0 | err: |
186 | 0 | if (ok != 1) |
187 | 0 | DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB); |
188 | |
|
189 | 0 | if (pub_key != dh->pub_key) |
190 | 0 | BN_free(pub_key); |
191 | 0 | if (priv_key != dh->priv_key) |
192 | 0 | BN_free(priv_key); |
193 | 0 | BN_CTX_free(ctx); |
194 | 0 | return ok; |
195 | 0 | } |
196 | | |
197 | | static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
198 | 0 | { |
199 | 0 | BN_CTX *ctx = NULL; |
200 | 0 | BN_MONT_CTX *mont = NULL; |
201 | 0 | BIGNUM *tmp; |
202 | 0 | int ret = -1; |
203 | 0 | int check_result; |
204 | |
|
205 | 0 | if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { |
206 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE); |
207 | 0 | goto err; |
208 | 0 | } |
209 | | |
210 | 0 | ctx = BN_CTX_new(); |
211 | 0 | if (ctx == NULL) |
212 | 0 | goto err; |
213 | 0 | BN_CTX_start(ctx); |
214 | 0 | tmp = BN_CTX_get(ctx); |
215 | 0 | if (tmp == NULL) |
216 | 0 | goto err; |
217 | | |
218 | 0 | if (dh->priv_key == NULL) { |
219 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE); |
220 | 0 | goto err; |
221 | 0 | } |
222 | | |
223 | 0 | if (dh->flags & DH_FLAG_CACHE_MONT_P) { |
224 | 0 | mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, |
225 | 0 | dh->lock, dh->p, ctx); |
226 | 0 | BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); |
227 | 0 | if (!mont) |
228 | 0 | goto err; |
229 | 0 | } |
230 | | |
231 | 0 | if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) { |
232 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY); |
233 | 0 | goto err; |
234 | 0 | } |
235 | | |
236 | 0 | if (!dh-> |
237 | 0 | meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) { |
238 | 0 | DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB); |
239 | 0 | goto err; |
240 | 0 | } |
241 | | |
242 | 0 | ret = BN_bn2binpad(tmp, key, BN_num_bytes(dh->p)); |
243 | 0 | err: |
244 | 0 | BN_CTX_end(ctx); |
245 | 0 | BN_CTX_free(ctx); |
246 | 0 | return ret; |
247 | 0 | } |
248 | | |
249 | | static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, |
250 | | const BIGNUM *a, const BIGNUM *p, |
251 | | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) |
252 | 0 | { |
253 | 0 | return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); |
254 | 0 | } |
255 | | |
256 | | static int dh_init(DH *dh) |
257 | 0 | { |
258 | 0 | dh->flags |= DH_FLAG_CACHE_MONT_P; |
259 | 0 | return 1; |
260 | 0 | } |
261 | | |
262 | | static int dh_finish(DH *dh) |
263 | 0 | { |
264 | 0 | BN_MONT_CTX_free(dh->method_mont_p); |
265 | 0 | return 1; |
266 | 0 | } |