xref: /freebsd/crypto/openssl/crypto/dh/dh_key.c (revision 19261079)
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 {
25     return dh->meth->generate_key(dh);
26 }
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 {
34     int ret = 0, i;
35     volatile size_t npad = 0, mask = 1;
36 
37     /* compute the key; ret is constant unless compute_key is external */
38     if ((ret = dh->meth->compute_key(key, pub_key, dh)) <= 0)
39         return ret;
40 
41     /* count leading zero bytes, yet still touch all bytes */
42     for (i = 0; i < ret; i++) {
43         mask &= !key[i];
44         npad += mask;
45     }
46 
47     /* unpad key */
48     ret -= npad;
49     /* key-dependent memory access, potentially leaking npad / ret */
50     memmove(key, key + npad, ret);
51     /* key-dependent memory access, potentially leaking npad / ret */
52     memset(key + ret, 0, npad);
53 
54     return ret;
55 }
56 
57 int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
58 {
59     int rv, pad;
60 
61     /* rv is constant unless compute_key is external */
62     rv = dh->meth->compute_key(key, pub_key, dh);
63     if (rv <= 0)
64         return rv;
65     pad = BN_num_bytes(dh->p) - rv;
66     /* pad is constant (zero) unless compute_key is external */
67     if (pad > 0) {
68         memmove(key + pad, key, rv);
69         memset(key, 0, pad);
70     }
71     return rv + pad;
72 }
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 {
90     return &dh_ossl;
91 }
92 
93 void DH_set_default_method(const DH_METHOD *meth)
94 {
95     default_DH_method = meth;
96 }
97 
98 const DH_METHOD *DH_get_default_method(void)
99 {
100     return default_DH_method;
101 }
102 
103 static int generate_key(DH *dh)
104 {
105     int ok = 0;
106     int generate_new_key = 0;
107     unsigned l;
108     BN_CTX *ctx = NULL;
109     BN_MONT_CTX *mont = NULL;
110     BIGNUM *pub_key = NULL, *priv_key = NULL;
111 
112     if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
113         DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
114         return 0;
115     }
116 
117     ctx = BN_CTX_new();
118     if (ctx == NULL)
119         goto err;
120 
121     if (dh->priv_key == NULL) {
122         priv_key = BN_secure_new();
123         if (priv_key == NULL)
124             goto err;
125         generate_new_key = 1;
126     } else
127         priv_key = dh->priv_key;
128 
129     if (dh->pub_key == NULL) {
130         pub_key = BN_new();
131         if (pub_key == NULL)
132             goto err;
133     } else
134         pub_key = dh->pub_key;
135 
136     if (dh->flags & DH_FLAG_CACHE_MONT_P) {
137         mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
138                                       dh->lock, dh->p, ctx);
139         if (!mont)
140             goto err;
141     }
142 
143     if (generate_new_key) {
144         if (dh->q) {
145             do {
146                 if (!BN_priv_rand_range(priv_key, dh->q))
147                     goto err;
148             }
149             while (BN_is_zero(priv_key) || BN_is_one(priv_key));
150         } else {
151             /* secret exponent length */
152             l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
153             if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
154                 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             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                 if (!BN_clear_bit(priv_key, 0))
162                     goto err;
163             }
164         }
165     }
166 
167     {
168         BIGNUM *prk = BN_new();
169 
170         if (prk == NULL)
171             goto err;
172         BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
173 
174         if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
175             BN_clear_free(prk);
176             goto err;
177         }
178         /* We MUST free prk before any further use of priv_key */
179         BN_clear_free(prk);
180     }
181 
182     dh->pub_key = pub_key;
183     dh->priv_key = priv_key;
184     ok = 1;
185  err:
186     if (ok != 1)
187         DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
188 
189     if (pub_key != dh->pub_key)
190         BN_free(pub_key);
191     if (priv_key != dh->priv_key)
192         BN_free(priv_key);
193     BN_CTX_free(ctx);
194     return ok;
195 }
196 
197 static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
198 {
199     BN_CTX *ctx = NULL;
200     BN_MONT_CTX *mont = NULL;
201     BIGNUM *tmp;
202     int ret = -1;
203     int check_result;
204 
205     if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
206         DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
207         goto err;
208     }
209 
210     ctx = BN_CTX_new();
211     if (ctx == NULL)
212         goto err;
213     BN_CTX_start(ctx);
214     tmp = BN_CTX_get(ctx);
215     if (tmp == NULL)
216         goto err;
217 
218     if (dh->priv_key == NULL) {
219         DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
220         goto err;
221     }
222 
223     if (dh->flags & DH_FLAG_CACHE_MONT_P) {
224         mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
225                                       dh->lock, dh->p, ctx);
226         BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
227         if (!mont)
228             goto err;
229     }
230 
231     if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
232         DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
233         goto err;
234     }
235 
236     if (!dh->
237         meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
238         DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
239         goto err;
240     }
241 
242     ret = BN_bn2binpad(tmp, key, BN_num_bytes(dh->p));
243  err:
244     BN_CTX_end(ctx);
245     BN_CTX_free(ctx);
246     return ret;
247 }
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 {
253     return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
254 }
255 
256 static int dh_init(DH *dh)
257 {
258     dh->flags |= DH_FLAG_CACHE_MONT_P;
259     return 1;
260 }
261 
262 static int dh_finish(DH *dh)
263 {
264     BN_MONT_CTX_free(dh->method_mont_p);
265     return 1;
266 }
267