diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-01-21 10:03:37 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-01-21 21:47:28 +1100 |
commit | dec5e9d33891e3bc3f1395d7db0e56fdc7f86dfc (patch) | |
tree | a91c7543cc726563651cc9eb2603f205ab7b27b1 /kexgexs.c | |
parent | e93bd98eab79b9a78f64ee8dd4dffc4d3979c7ae (diff) |
upstream: factor out kex_dh_compute_key() - it's shared between
plain DH KEX and DH GEX in both the client and server implementations
from markus@ ok djm@
OpenBSD-Commit-ID: 12186e18791fffcd4642c82e7e0cfdd7ea37e2ec
Diffstat (limited to 'kexgexs.c')
-rw-r--r-- | kexgexs.c | 58 |
1 files changed, 14 insertions, 44 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexgexs.c,v 1.39 2019/01/21 09:55:52 djm Exp $ */ | 1 | /* $OpenBSD: kexgexs.c,v 1.40 2019/01/21 10:03:37 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Niels Provos. All rights reserved. | 3 | * Copyright (c) 2000 Niels Provos. All rights reserved. |
4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
@@ -126,14 +126,15 @@ static int | |||
126 | input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | 126 | input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) |
127 | { | 127 | { |
128 | struct kex *kex = ssh->kex; | 128 | struct kex *kex = ssh->kex; |
129 | BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; | 129 | BIGNUM *dh_client_pub = NULL; |
130 | const BIGNUM *pub_key, *dh_p, *dh_g; | 130 | const BIGNUM *pub_key, *dh_p, *dh_g; |
131 | struct sshbuf *shared_secret = NULL; | ||
131 | struct sshkey *server_host_public, *server_host_private; | 132 | struct sshkey *server_host_public, *server_host_private; |
132 | u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; | 133 | u_char *signature = NULL, *server_host_key_blob = NULL; |
133 | u_char hash[SSH_DIGEST_MAX_LENGTH]; | 134 | u_char hash[SSH_DIGEST_MAX_LENGTH]; |
134 | size_t sbloblen, slen; | 135 | size_t sbloblen, slen; |
135 | size_t klen = 0, hashlen; | 136 | size_t hashlen; |
136 | int kout, r; | 137 | int r; |
137 | 138 | ||
138 | if (kex->load_host_public_key == NULL || | 139 | if (kex->load_host_public_key == NULL || |
139 | kex->load_host_private_key == NULL) { | 140 | kex->load_host_private_key == NULL) { |
@@ -153,44 +154,19 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | |||
153 | if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || | 154 | if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || |
154 | (r = sshpkt_get_end(ssh)) != 0) | 155 | (r = sshpkt_get_end(ssh)) != 0) |
155 | goto out; | 156 | goto out; |
156 | 157 | if ((shared_secret = sshbuf_new()) == NULL) { | |
157 | DH_get0_key(kex->dh, &pub_key, NULL); | ||
158 | DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); | ||
159 | |||
160 | #ifdef DEBUG_KEXDH | ||
161 | fprintf(stderr, "dh_client_pub= "); | ||
162 | BN_print_fp(stderr, dh_client_pub); | ||
163 | fprintf(stderr, "\n"); | ||
164 | debug("bits %d", BN_num_bits(dh_client_pub)); | ||
165 | DHparams_print_fp(stderr, kex->dh); | ||
166 | fprintf(stderr, "pub= "); | ||
167 | BN_print_fp(stderr, pub_key); | ||
168 | fprintf(stderr, "\n"); | ||
169 | #endif | ||
170 | if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { | ||
171 | sshpkt_disconnect(ssh, "bad client public DH value"); | ||
172 | r = SSH_ERR_MESSAGE_INCOMPLETE; | ||
173 | goto out; | ||
174 | } | ||
175 | |||
176 | klen = DH_size(kex->dh); | ||
177 | if ((kbuf = malloc(klen)) == NULL || | ||
178 | (shared_secret = BN_new()) == NULL) { | ||
179 | r = SSH_ERR_ALLOC_FAIL; | 158 | r = SSH_ERR_ALLOC_FAIL; |
180 | goto out; | 159 | goto out; |
181 | } | 160 | } |
182 | if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || | 161 | if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) |
183 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) { | ||
184 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
185 | goto out; | 162 | goto out; |
186 | } | ||
187 | #ifdef DEBUG_KEXDH | ||
188 | dump_digest("shared secret", kbuf, kout); | ||
189 | #endif | ||
190 | if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, | 163 | if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, |
191 | &sbloblen)) != 0) | 164 | &sbloblen)) != 0) |
192 | goto out; | 165 | goto out; |
166 | |||
193 | /* calc H */ | 167 | /* calc H */ |
168 | DH_get0_key(kex->dh, &pub_key, NULL); | ||
169 | DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); | ||
194 | hashlen = sizeof(hash); | 170 | hashlen = sizeof(hash); |
195 | if ((r = kexgex_hash( | 171 | if ((r = kexgex_hash( |
196 | kex->hash_alg, | 172 | kex->hash_alg, |
@@ -203,7 +179,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | |||
203 | dh_p, dh_g, | 179 | dh_p, dh_g, |
204 | dh_client_pub, | 180 | dh_client_pub, |
205 | pub_key, | 181 | pub_key, |
206 | shared_secret, | 182 | sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), |
207 | hash, &hashlen)) != 0) | 183 | hash, &hashlen)) != 0) |
208 | goto out; | 184 | goto out; |
209 | 185 | ||
@@ -212,8 +188,6 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | |||
212 | &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) | 188 | &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) |
213 | goto out; | 189 | goto out; |
214 | 190 | ||
215 | /* destroy_sensitive_data(); */ | ||
216 | |||
217 | /* send server hostkey, DH pubkey 'f' and signed H */ | 191 | /* send server hostkey, DH pubkey 'f' and signed H */ |
218 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || | 192 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || |
219 | (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || | 193 | (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || |
@@ -222,18 +196,14 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) | |||
222 | (r = sshpkt_send(ssh)) != 0) | 196 | (r = sshpkt_send(ssh)) != 0) |
223 | goto out; | 197 | goto out; |
224 | 198 | ||
225 | if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) | 199 | if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) |
226 | r = kex_send_newkeys(ssh); | 200 | r = kex_send_newkeys(ssh); |
227 | out: | 201 | out: |
228 | explicit_bzero(hash, sizeof(hash)); | 202 | explicit_bzero(hash, sizeof(hash)); |
229 | DH_free(kex->dh); | 203 | DH_free(kex->dh); |
230 | kex->dh = NULL; | 204 | kex->dh = NULL; |
231 | BN_clear_free(dh_client_pub); | 205 | BN_clear_free(dh_client_pub); |
232 | if (kbuf) { | 206 | sshbuf_free(shared_secret); |
233 | explicit_bzero(kbuf, klen); | ||
234 | free(kbuf); | ||
235 | } | ||
236 | BN_clear_free(shared_secret); | ||
237 | free(server_host_key_blob); | 207 | free(server_host_key_blob); |
238 | free(signature); | 208 | free(signature); |
239 | return r; | 209 | return r; |