]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dh/dh_key.c
Useless header include of openssl/rand.h
[thirdparty/openssl.git] / crypto / dh / dh_key.c
1 /*
2 * Copyright 1995-2016 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 {
25 return dh->meth->generate_key(dh);
26 }
27
28 int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
29 {
30 return dh->meth->compute_key(key, pub_key, dh);
31 }
32
33 int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
34 {
35 int rv, pad;
36 rv = dh->meth->compute_key(key, pub_key, dh);
37 if (rv <= 0)
38 return rv;
39 pad = BN_num_bytes(dh->p) - rv;
40 if (pad > 0) {
41 memmove(key + pad, key, rv);
42 memset(key, 0, pad);
43 }
44 return rv + pad;
45 }
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 const DH_METHOD *DH_OpenSSL(void)
60 {
61 return &dh_ossl;
62 }
63
64 static int generate_key(DH *dh)
65 {
66 int ok = 0;
67 int generate_new_key = 0;
68 unsigned l;
69 BN_CTX *ctx;
70 BN_MONT_CTX *mont = NULL;
71 BIGNUM *pub_key = NULL, *priv_key = NULL;
72
73 ctx = BN_CTX_new();
74 if (ctx == NULL)
75 goto err;
76
77 if (dh->priv_key == NULL) {
78 priv_key = BN_secure_new();
79 if (priv_key == NULL)
80 goto err;
81 generate_new_key = 1;
82 } else
83 priv_key = dh->priv_key;
84
85 if (dh->pub_key == NULL) {
86 pub_key = BN_new();
87 if (pub_key == NULL)
88 goto err;
89 } else
90 pub_key = dh->pub_key;
91
92 if (dh->flags & DH_FLAG_CACHE_MONT_P) {
93 mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
94 dh->lock, dh->p, ctx);
95 if (!mont)
96 goto err;
97 }
98
99 if (generate_new_key) {
100 if (dh->q) {
101 do {
102 if (!BN_rand_range(priv_key, dh->q))
103 goto err;
104 }
105 while (BN_is_zero(priv_key) || BN_is_one(priv_key));
106 } else {
107 /* secret exponent length */
108 l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
109 if (!BN_rand(priv_key, l, 0, 0))
110 goto err;
111 }
112 }
113
114 {
115 BIGNUM *prk = BN_new();
116
117 if (prk == NULL)
118 goto err;
119 BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
120
121 if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
122 BN_free(prk);
123 goto err;
124 }
125 /* We MUST free prk before any further use of priv_key */
126 BN_free(prk);
127 }
128
129 dh->pub_key = pub_key;
130 dh->priv_key = priv_key;
131 ok = 1;
132 err:
133 if (ok != 1)
134 DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
135
136 if (pub_key != dh->pub_key)
137 BN_free(pub_key);
138 if (priv_key != dh->priv_key)
139 BN_free(priv_key);
140 BN_CTX_free(ctx);
141 return (ok);
142 }
143
144 static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
145 {
146 BN_CTX *ctx = NULL;
147 BN_MONT_CTX *mont = NULL;
148 BIGNUM *tmp;
149 int ret = -1;
150 int check_result;
151
152 if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
153 DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
154 goto err;
155 }
156
157 ctx = BN_CTX_new();
158 if (ctx == NULL)
159 goto err;
160 BN_CTX_start(ctx);
161 tmp = BN_CTX_get(ctx);
162
163 if (dh->priv_key == NULL) {
164 DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
165 goto err;
166 }
167
168 if (dh->flags & DH_FLAG_CACHE_MONT_P) {
169 mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
170 dh->lock, dh->p, ctx);
171 BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
172 if (!mont)
173 goto err;
174 }
175
176 if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
177 DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
178 goto err;
179 }
180
181 if (!dh->
182 meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
183 DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
184 goto err;
185 }
186
187 ret = BN_bn2bin(tmp, key);
188 err:
189 if (ctx != NULL) {
190 BN_CTX_end(ctx);
191 BN_CTX_free(ctx);
192 }
193 return (ret);
194 }
195
196 static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
197 const BIGNUM *a, const BIGNUM *p,
198 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
199 {
200 return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
201 }
202
203 static int dh_init(DH *dh)
204 {
205 dh->flags |= DH_FLAG_CACHE_MONT_P;
206 return (1);
207 }
208
209 static int dh_finish(DH *dh)
210 {
211 BN_MONT_CTX_free(dh->method_mont_p);
212 return (1);
213 }