/src/openssl/crypto/dh/dh_key.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1995-2018 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_locl.h" |
13 | | #include "internal/bn_int.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 | | int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
29 | 0 | { |
30 | 0 | return dh->meth->compute_key(key, pub_key, dh); |
31 | 0 | } |
32 | | |
33 | | int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
34 | 0 | { |
35 | 0 | int rv, pad; |
36 | 0 | rv = dh->meth->compute_key(key, pub_key, dh); |
37 | 0 | if (rv <= 0) |
38 | 0 | return rv; |
39 | 0 | pad = BN_num_bytes(dh->p) - rv; |
40 | 0 | if (pad > 0) { |
41 | 0 | memmove(key + pad, key, rv); |
42 | 0 | memset(key, 0, pad); |
43 | 0 | } |
44 | 0 | return rv + pad; |
45 | 0 | } |
46 | | |
47 | | static DH_METHOD dh_ossl = { |
48 | | "OpenSSL DH Method", |
49 | | generate_key, |
50 | | compute_key, |
51 | | dh_bn_mod_exp, |
52 | | dh_init, |
53 | | dh_finish, |
54 | | DH_FLAG_FIPS_METHOD, |
55 | | NULL, |
56 | | NULL |
57 | | }; |
58 | | |
59 | | static const DH_METHOD *default_DH_method = &dh_ossl; |
60 | | |
61 | | const DH_METHOD *DH_OpenSSL(void) |
62 | 0 | { |
63 | 0 | return &dh_ossl; |
64 | 0 | } |
65 | | |
66 | | void DH_set_default_method(const DH_METHOD *meth) |
67 | 0 | { |
68 | 0 | default_DH_method = meth; |
69 | 0 | } |
70 | | |
71 | | const DH_METHOD *DH_get_default_method(void) |
72 | 0 | { |
73 | 0 | return default_DH_method; |
74 | 0 | } |
75 | | |
76 | | static int generate_key(DH *dh) |
77 | 0 | { |
78 | 0 | int ok = 0; |
79 | 0 | int generate_new_key = 0; |
80 | 0 | unsigned l; |
81 | 0 | BN_CTX *ctx = NULL; |
82 | 0 | BN_MONT_CTX *mont = NULL; |
83 | 0 | BIGNUM *pub_key = NULL, *priv_key = NULL; |
84 | 0 |
|
85 | 0 | if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { |
86 | 0 | DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE); |
87 | 0 | return 0; |
88 | 0 | } |
89 | 0 |
|
90 | 0 | ctx = BN_CTX_new(); |
91 | 0 | if (ctx == NULL) |
92 | 0 | goto err; |
93 | 0 | |
94 | 0 | if (dh->priv_key == NULL) { |
95 | 0 | priv_key = BN_secure_new(); |
96 | 0 | if (priv_key == NULL) |
97 | 0 | goto err; |
98 | 0 | generate_new_key = 1; |
99 | 0 | } else |
100 | 0 | priv_key = dh->priv_key; |
101 | 0 |
|
102 | 0 | if (dh->pub_key == NULL) { |
103 | 0 | pub_key = BN_new(); |
104 | 0 | if (pub_key == NULL) |
105 | 0 | goto err; |
106 | 0 | } else |
107 | 0 | pub_key = dh->pub_key; |
108 | 0 |
|
109 | 0 | if (dh->flags & DH_FLAG_CACHE_MONT_P) { |
110 | 0 | mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, |
111 | 0 | dh->lock, dh->p, ctx); |
112 | 0 | if (!mont) |
113 | 0 | goto err; |
114 | 0 | } |
115 | 0 | |
116 | 0 | if (generate_new_key) { |
117 | 0 | if (dh->q) { |
118 | 0 | do { |
119 | 0 | if (!BN_priv_rand_range(priv_key, dh->q)) |
120 | 0 | goto err; |
121 | 0 | } |
122 | 0 | while (BN_is_zero(priv_key) || BN_is_one(priv_key)); |
123 | 0 | } else { |
124 | 0 | /* secret exponent length */ |
125 | 0 | l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; |
126 | 0 | if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) |
127 | 0 | goto err; |
128 | 0 | } |
129 | 0 | } |
130 | 0 | |
131 | 0 | { |
132 | 0 | BIGNUM *prk = BN_new(); |
133 | 0 |
|
134 | 0 | if (prk == NULL) |
135 | 0 | goto err; |
136 | 0 | BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); |
137 | 0 |
|
138 | 0 | if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) { |
139 | 0 | BN_free(prk); |
140 | 0 | goto err; |
141 | 0 | } |
142 | 0 | /* We MUST free prk before any further use of priv_key */ |
143 | 0 | BN_free(prk); |
144 | 0 | } |
145 | 0 |
|
146 | 0 | dh->pub_key = pub_key; |
147 | 0 | dh->priv_key = priv_key; |
148 | 0 | ok = 1; |
149 | 0 | err: |
150 | 0 | if (ok != 1) |
151 | 0 | DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB); |
152 | 0 |
|
153 | 0 | if (pub_key != dh->pub_key) |
154 | 0 | BN_free(pub_key); |
155 | 0 | if (priv_key != dh->priv_key) |
156 | 0 | BN_free(priv_key); |
157 | 0 | BN_CTX_free(ctx); |
158 | 0 | return ok; |
159 | 0 | } |
160 | | |
161 | | static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) |
162 | 0 | { |
163 | 0 | BN_CTX *ctx = NULL; |
164 | 0 | BN_MONT_CTX *mont = NULL; |
165 | 0 | BIGNUM *tmp; |
166 | 0 | int ret = -1; |
167 | 0 | int check_result; |
168 | 0 |
|
169 | 0 | if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { |
170 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE); |
171 | 0 | goto err; |
172 | 0 | } |
173 | 0 |
|
174 | 0 | ctx = BN_CTX_new(); |
175 | 0 | if (ctx == NULL) |
176 | 0 | goto err; |
177 | 0 | BN_CTX_start(ctx); |
178 | 0 | tmp = BN_CTX_get(ctx); |
179 | 0 | if (tmp == NULL) |
180 | 0 | goto err; |
181 | 0 | |
182 | 0 | if (dh->priv_key == NULL) { |
183 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE); |
184 | 0 | goto err; |
185 | 0 | } |
186 | 0 |
|
187 | 0 | if (dh->flags & DH_FLAG_CACHE_MONT_P) { |
188 | 0 | mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, |
189 | 0 | dh->lock, dh->p, ctx); |
190 | 0 | BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); |
191 | 0 | if (!mont) |
192 | 0 | goto err; |
193 | 0 | } |
194 | 0 | |
195 | 0 | if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) { |
196 | 0 | DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY); |
197 | 0 | goto err; |
198 | 0 | } |
199 | 0 |
|
200 | 0 | if (!dh-> |
201 | 0 | meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) { |
202 | 0 | DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB); |
203 | 0 | goto err; |
204 | 0 | } |
205 | 0 |
|
206 | 0 | ret = BN_bn2bin(tmp, key); |
207 | 0 | err: |
208 | 0 | if (ctx != NULL) { |
209 | 0 | BN_CTX_end(ctx); |
210 | 0 | BN_CTX_free(ctx); |
211 | 0 | } |
212 | 0 | return ret; |
213 | 0 | } |
214 | | |
215 | | static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, |
216 | | const BIGNUM *a, const BIGNUM *p, |
217 | | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) |
218 | 0 | { |
219 | 0 | return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); |
220 | 0 | } |
221 | | |
222 | | static int dh_init(DH *dh) |
223 | 0 | { |
224 | 0 | dh->flags |= DH_FLAG_CACHE_MONT_P; |
225 | 0 | return 1; |
226 | 0 | } |
227 | | |
228 | | static int dh_finish(DH *dh) |
229 | 0 | { |
230 | 0 | BN_MONT_CTX_free(dh->method_mont_p); |
231 | 0 | return 1; |
232 | 0 | } |