diff options
-rw-r--r-- | kex.h | 7 | ||||
-rw-r--r-- | kexdh.c | 49 | ||||
-rw-r--r-- | kexdhc.c | 45 | ||||
-rw-r--r-- | kexdhs.c | 54 | ||||
-rw-r--r-- | kexgex.c | 6 | ||||
-rw-r--r-- | kexgexc.c | 45 | ||||
-rw-r--r-- | kexgexs.c | 58 |
7 files changed, 101 insertions, 163 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.95 2019/01/21 10:00:23 djm Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.96 2019/01/21 10:03:37 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -203,15 +203,16 @@ int kexc25519_client(struct ssh *); | |||
203 | int kexc25519_server(struct ssh *); | 203 | int kexc25519_server(struct ssh *); |
204 | 204 | ||
205 | int kex_dh_keygen(struct kex *); | 205 | int kex_dh_keygen(struct kex *); |
206 | int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); | ||
206 | int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, | 207 | int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, |
207 | const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, | 208 | const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, |
208 | const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); | 209 | const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); |
209 | 210 | ||
210 | int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, | 211 | int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, |
211 | const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, | 212 | const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, |
212 | int, int, int, | 213 | int, int, int, |
213 | const BIGNUM *, const BIGNUM *, const BIGNUM *, | 214 | const BIGNUM *, const BIGNUM *, const BIGNUM *, |
214 | const BIGNUM *, const BIGNUM *, | 215 | const BIGNUM *, const u_char *, size_t, |
215 | u_char *, size_t *); | 216 | u_char *, size_t *); |
216 | 217 | ||
217 | int kex_ecdh_hash(int, const EC_GROUP *, | 218 | int kex_ecdh_hash(int, const EC_GROUP *, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexdh.c,v 1.28 2019/01/21 10:00:23 djm Exp $ */ | 1 | /* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -43,6 +43,7 @@ | |||
43 | #include "ssherr.h" | 43 | #include "ssherr.h" |
44 | #include "sshbuf.h" | 44 | #include "sshbuf.h" |
45 | #include "digest.h" | 45 | #include "digest.h" |
46 | #include "dh.h" | ||
46 | 47 | ||
47 | int | 48 | int |
48 | kex_dh_keygen(struct kex *kex) | 49 | kex_dh_keygen(struct kex *kex) |
@@ -70,6 +71,48 @@ kex_dh_keygen(struct kex *kex) | |||
70 | } | 71 | } |
71 | 72 | ||
72 | int | 73 | int |
74 | kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) | ||
75 | { | ||
76 | BIGNUM *shared_secret = NULL; | ||
77 | u_char *kbuf = NULL; | ||
78 | size_t klen = 0; | ||
79 | int kout, r; | ||
80 | |||
81 | #ifdef DEBUG_KEXDH | ||
82 | fprintf(stderr, "dh_pub= "); | ||
83 | BN_print_fp(stderr, dh_pub); | ||
84 | fprintf(stderr, "\n"); | ||
85 | debug("bits %d", BN_num_bits(dh_pub)); | ||
86 | DHparams_print_fp(stderr, kex->dh); | ||
87 | fprintf(stderr, "\n"); | ||
88 | #endif | ||
89 | |||
90 | if (!dh_pub_is_valid(kex->dh, dh_pub)) { | ||
91 | r = SSH_ERR_MESSAGE_INCOMPLETE; | ||
92 | goto out; | ||
93 | } | ||
94 | klen = DH_size(kex->dh); | ||
95 | if ((kbuf = malloc(klen)) == NULL || | ||
96 | (shared_secret = BN_new()) == NULL) { | ||
97 | r = SSH_ERR_ALLOC_FAIL; | ||
98 | goto out; | ||
99 | } | ||
100 | if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || | ||
101 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) { | ||
102 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
103 | goto out; | ||
104 | } | ||
105 | #ifdef DEBUG_KEXDH | ||
106 | dump_digest("shared secret", kbuf, kout); | ||
107 | #endif | ||
108 | r = sshbuf_put_bignum2(out, shared_secret); | ||
109 | out: | ||
110 | freezero(kbuf, klen); | ||
111 | BN_clear_free(shared_secret); | ||
112 | return r; | ||
113 | } | ||
114 | |||
115 | int | ||
73 | kex_dh_hash( | 116 | kex_dh_hash( |
74 | int hash_alg, | 117 | int hash_alg, |
75 | const struct sshbuf *client_version, | 118 | const struct sshbuf *client_version, |
@@ -79,7 +122,7 @@ kex_dh_hash( | |||
79 | const u_char *serverhostkeyblob, size_t sbloblen, | 122 | const u_char *serverhostkeyblob, size_t sbloblen, |
80 | const BIGNUM *client_dh_pub, | 123 | const BIGNUM *client_dh_pub, |
81 | const BIGNUM *server_dh_pub, | 124 | const BIGNUM *server_dh_pub, |
82 | const BIGNUM *shared_secret, | 125 | const u_char *shared_secret, size_t secretlen, |
83 | u_char *hash, size_t *hashlen) | 126 | u_char *hash, size_t *hashlen) |
84 | { | 127 | { |
85 | struct sshbuf *b; | 128 | struct sshbuf *b; |
@@ -101,7 +144,7 @@ kex_dh_hash( | |||
101 | (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || | 144 | (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || |
102 | (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || | 145 | (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || |
103 | (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || | 146 | (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || |
104 | (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { | 147 | (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { |
105 | sshbuf_free(b); | 148 | sshbuf_free(b); |
106 | return r; | 149 | return r; |
107 | } | 150 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexdhc.c,v 1.27 2019/01/21 10:00:23 djm Exp $ */ | 1 | /* $OpenBSD: kexdhc.c,v 1.28 2019/01/21 10:03:37 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -86,13 +86,14 @@ static int | |||
86 | input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) | 86 | input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) |
87 | { | 87 | { |
88 | struct kex *kex = ssh->kex; | 88 | struct kex *kex = ssh->kex; |
89 | BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; | 89 | BIGNUM *dh_server_pub = NULL; |
90 | const BIGNUM *pub_key; | 90 | const BIGNUM *pub_key; |
91 | struct sshkey *server_host_key = NULL; | 91 | struct sshkey *server_host_key = NULL; |
92 | u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL; | 92 | struct sshbuf *shared_secret = NULL; |
93 | u_char *server_host_key_blob = NULL, *signature = NULL; | ||
93 | u_char hash[SSH_DIGEST_MAX_LENGTH]; | 94 | u_char hash[SSH_DIGEST_MAX_LENGTH]; |
94 | size_t klen = 0, slen, sbloblen, hashlen; | 95 | size_t slen, sbloblen, hashlen; |
95 | int kout, r; | 96 | int r; |
96 | 97 | ||
97 | if (kex->verify_host_key == NULL) { | 98 | if (kex->verify_host_key == NULL) { |
98 | r = SSH_ERR_INVALID_ARGUMENT; | 99 | r = SSH_ERR_INVALID_ARGUMENT; |
@@ -119,32 +120,12 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) | |||
119 | (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || | 120 | (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || |
120 | (r = sshpkt_get_end(ssh)) != 0) | 121 | (r = sshpkt_get_end(ssh)) != 0) |
121 | goto out; | 122 | goto out; |
122 | #ifdef DEBUG_KEXDH | 123 | if ((shared_secret = sshbuf_new()) == NULL) { |
123 | fprintf(stderr, "dh_server_pub= "); | ||
124 | BN_print_fp(stderr, dh_server_pub); | ||
125 | fprintf(stderr, "\n"); | ||
126 | debug("bits %d", BN_num_bits(dh_server_pub)); | ||
127 | #endif | ||
128 | if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { | ||
129 | sshpkt_disconnect(ssh, "bad server public DH value"); | ||
130 | r = SSH_ERR_MESSAGE_INCOMPLETE; | ||
131 | goto out; | ||
132 | } | ||
133 | |||
134 | klen = DH_size(kex->dh); | ||
135 | if ((kbuf = malloc(klen)) == NULL || | ||
136 | (shared_secret = BN_new()) == NULL) { | ||
137 | r = SSH_ERR_ALLOC_FAIL; | 124 | r = SSH_ERR_ALLOC_FAIL; |
138 | goto out; | 125 | goto out; |
139 | } | 126 | } |
140 | if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || | 127 | if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) |
141 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) { | ||
142 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
143 | goto out; | 128 | goto out; |
144 | } | ||
145 | #ifdef DEBUG_KEXDH | ||
146 | dump_digest("shared secret", kbuf, kout); | ||
147 | #endif | ||
148 | 129 | ||
149 | /* calc and verify H */ | 130 | /* calc and verify H */ |
150 | DH_get0_key(kex->dh, &pub_key, NULL); | 131 | DH_get0_key(kex->dh, &pub_key, NULL); |
@@ -158,7 +139,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) | |||
158 | server_host_key_blob, sbloblen, | 139 | server_host_key_blob, sbloblen, |
159 | pub_key, | 140 | pub_key, |
160 | dh_server_pub, | 141 | dh_server_pub, |
161 | shared_secret, | 142 | sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), |
162 | hash, &hashlen)) != 0) | 143 | hash, &hashlen)) != 0) |
163 | goto out; | 144 | goto out; |
164 | 145 | ||
@@ -166,18 +147,14 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) | |||
166 | kex->hostkey_alg, ssh->compat)) != 0) | 147 | kex->hostkey_alg, ssh->compat)) != 0) |
167 | goto out; | 148 | goto out; |
168 | 149 | ||
169 | if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) | 150 | if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) |
170 | r = kex_send_newkeys(ssh); | 151 | r = kex_send_newkeys(ssh); |
171 | out: | 152 | out: |
172 | explicit_bzero(hash, sizeof(hash)); | 153 | explicit_bzero(hash, sizeof(hash)); |
173 | DH_free(kex->dh); | 154 | DH_free(kex->dh); |
174 | kex->dh = NULL; | 155 | kex->dh = NULL; |
175 | BN_clear_free(dh_server_pub); | 156 | BN_clear_free(dh_server_pub); |
176 | if (kbuf) { | 157 | sshbuf_free(shared_secret); |
177 | explicit_bzero(kbuf, klen); | ||
178 | free(kbuf); | ||
179 | } | ||
180 | BN_clear_free(shared_secret); | ||
181 | sshkey_free(server_host_key); | 158 | sshkey_free(server_host_key); |
182 | free(server_host_key_blob); | 159 | free(server_host_key_blob); |
183 | free(signature); | 160 | free(signature); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexdhs.c,v 1.33 2019/01/21 10:00:23 djm Exp $ */ | 1 | /* $OpenBSD: kexdhs.c,v 1.34 2019/01/21 10:03:37 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -71,14 +71,15 @@ int | |||
71 | input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) | 71 | input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) |
72 | { | 72 | { |
73 | struct kex *kex = ssh->kex; | 73 | struct kex *kex = ssh->kex; |
74 | BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; | 74 | BIGNUM *dh_client_pub = NULL; |
75 | const BIGNUM *pub_key; | 75 | const BIGNUM *pub_key; |
76 | struct sshkey *server_host_public, *server_host_private; | 76 | struct sshkey *server_host_public, *server_host_private; |
77 | u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; | 77 | struct sshbuf *shared_secret = NULL; |
78 | u_char *signature = NULL, *server_host_key_blob = NULL; | ||
78 | u_char hash[SSH_DIGEST_MAX_LENGTH]; | 79 | u_char hash[SSH_DIGEST_MAX_LENGTH]; |
79 | size_t sbloblen, slen; | 80 | size_t sbloblen, slen; |
80 | size_t klen = 0, hashlen; | 81 | size_t hashlen; |
81 | int kout, r; | 82 | int r; |
82 | 83 | ||
83 | if (kex->load_host_public_key == NULL || | 84 | if (kex->load_host_public_key == NULL || |
84 | kex->load_host_private_key == NULL) { | 85 | kex->load_host_private_key == NULL) { |
@@ -98,42 +99,17 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) | |||
98 | if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || | 99 | if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || |
99 | (r = sshpkt_get_end(ssh)) != 0) | 100 | (r = sshpkt_get_end(ssh)) != 0) |
100 | goto out; | 101 | goto out; |
101 | DH_get0_key(kex->dh, &pub_key, NULL); | 102 | if ((shared_secret = sshbuf_new()) == NULL) { |
102 | |||
103 | #ifdef DEBUG_KEXDH | ||
104 | fprintf(stderr, "dh_client_pub= "); | ||
105 | BN_print_fp(stderr, dh_client_pub); | ||
106 | fprintf(stderr, "\n"); | ||
107 | debug("bits %d", BN_num_bits(dh_client_pub)); | ||
108 | DHparams_print_fp(stderr, kex->dh); | ||
109 | fprintf(stderr, "pub= "); | ||
110 | BN_print_fp(stderr, pub_key); | ||
111 | fprintf(stderr, "\n"); | ||
112 | #endif | ||
113 | if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { | ||
114 | sshpkt_disconnect(ssh, "bad client public DH value"); | ||
115 | r = SSH_ERR_MESSAGE_INCOMPLETE; | ||
116 | goto out; | ||
117 | } | ||
118 | |||
119 | klen = DH_size(kex->dh); | ||
120 | if ((kbuf = malloc(klen)) == NULL || | ||
121 | (shared_secret = BN_new()) == NULL) { | ||
122 | r = SSH_ERR_ALLOC_FAIL; | 103 | r = SSH_ERR_ALLOC_FAIL; |
123 | goto out; | 104 | goto out; |
124 | } | 105 | } |
125 | if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || | 106 | if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) |
126 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) { | ||
127 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
128 | goto out; | 107 | goto out; |
129 | } | ||
130 | #ifdef DEBUG_KEXDH | ||
131 | dump_digest("shared secret", kbuf, kout); | ||
132 | #endif | ||
133 | if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, | 108 | if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, |
134 | &sbloblen)) != 0) | 109 | &sbloblen)) != 0) |
135 | goto out; | 110 | goto out; |
136 | /* calc H */ | 111 | /* calc H */ |
112 | DH_get0_key(kex->dh, &pub_key, NULL); | ||
137 | hashlen = sizeof(hash); | 113 | hashlen = sizeof(hash); |
138 | if ((r = kex_dh_hash( | 114 | if ((r = kex_dh_hash( |
139 | kex->hash_alg, | 115 | kex->hash_alg, |
@@ -144,7 +120,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) | |||
144 | server_host_key_blob, sbloblen, | 120 | server_host_key_blob, sbloblen, |
145 | dh_client_pub, | 121 | dh_client_pub, |
146 | pub_key, | 122 | pub_key, |
147 | shared_secret, | 123 | sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), |
148 | hash, &hashlen)) != 0) | 124 | hash, &hashlen)) != 0) |
149 | goto out; | 125 | goto out; |
150 | 126 | ||
@@ -153,8 +129,6 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) | |||
153 | &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) | 129 | &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) |
154 | goto out; | 130 | goto out; |
155 | 131 | ||
156 | /* destroy_sensitive_data(); */ | ||
157 | |||
158 | /* send server hostkey, DH pubkey 'f' and signed H */ | 132 | /* send server hostkey, DH pubkey 'f' and signed H */ |
159 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || | 133 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || |
160 | (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || | 134 | (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || |
@@ -163,18 +137,14 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) | |||
163 | (r = sshpkt_send(ssh)) != 0) | 137 | (r = sshpkt_send(ssh)) != 0) |
164 | goto out; | 138 | goto out; |
165 | 139 | ||
166 | if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) | 140 | if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) |
167 | r = kex_send_newkeys(ssh); | 141 | r = kex_send_newkeys(ssh); |
168 | out: | 142 | out: |
169 | explicit_bzero(hash, sizeof(hash)); | 143 | explicit_bzero(hash, sizeof(hash)); |
170 | DH_free(kex->dh); | 144 | DH_free(kex->dh); |
171 | kex->dh = NULL; | 145 | kex->dh = NULL; |
172 | BN_clear_free(dh_client_pub); | 146 | BN_clear_free(dh_client_pub); |
173 | if (kbuf) { | 147 | sshbuf_free(shared_secret); |
174 | explicit_bzero(kbuf, klen); | ||
175 | free(kbuf); | ||
176 | } | ||
177 | BN_clear_free(shared_secret); | ||
178 | free(server_host_key_blob); | 148 | free(server_host_key_blob); |
179 | free(signature); | 149 | free(signature); |
180 | return r; | 150 | return r; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */ | 1 | /* $OpenBSD: kexgex.c,v 1.31 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. |
@@ -56,7 +56,7 @@ kexgex_hash( | |||
56 | const BIGNUM *gen, | 56 | const BIGNUM *gen, |
57 | const BIGNUM *client_dh_pub, | 57 | const BIGNUM *client_dh_pub, |
58 | const BIGNUM *server_dh_pub, | 58 | const BIGNUM *server_dh_pub, |
59 | const BIGNUM *shared_secret, | 59 | const u_char *shared_secret, size_t secretlen, |
60 | u_char *hash, size_t *hashlen) | 60 | u_char *hash, size_t *hashlen) |
61 | { | 61 | { |
62 | struct sshbuf *b; | 62 | struct sshbuf *b; |
@@ -83,7 +83,7 @@ kexgex_hash( | |||
83 | (r = sshbuf_put_bignum2(b, gen)) != 0 || | 83 | (r = sshbuf_put_bignum2(b, gen)) != 0 || |
84 | (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || | 84 | (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || |
85 | (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || | 85 | (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || |
86 | (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { | 86 | (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { |
87 | sshbuf_free(b); | 87 | sshbuf_free(b); |
88 | return r; | 88 | return r; |
89 | } | 89 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexgexc.c,v 1.31 2019/01/21 09:55:52 djm Exp $ */ | 1 | /* $OpenBSD: kexgexc.c,v 1.32 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. |
@@ -143,13 +143,14 @@ static int | |||
143 | input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) | 143 | input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) |
144 | { | 144 | { |
145 | struct kex *kex = ssh->kex; | 145 | struct kex *kex = ssh->kex; |
146 | BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; | 146 | BIGNUM *dh_server_pub = NULL; |
147 | const BIGNUM *pub_key, *dh_p, *dh_g; | 147 | const BIGNUM *pub_key, *dh_p, *dh_g; |
148 | struct sshbuf *shared_secret = NULL; | ||
148 | struct sshkey *server_host_key = NULL; | 149 | struct sshkey *server_host_key = NULL; |
149 | u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; | 150 | u_char *signature = NULL, *server_host_key_blob = NULL; |
150 | u_char hash[SSH_DIGEST_MAX_LENGTH]; | 151 | u_char hash[SSH_DIGEST_MAX_LENGTH]; |
151 | size_t klen = 0, slen, sbloblen, hashlen; | 152 | size_t slen, sbloblen, hashlen; |
152 | int kout, r; | 153 | int r; |
153 | 154 | ||
154 | debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); | 155 | debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); |
155 | if (kex->verify_host_key == NULL) { | 156 | if (kex->verify_host_key == NULL) { |
@@ -177,32 +178,12 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) | |||
177 | (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || | 178 | (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || |
178 | (r = sshpkt_get_end(ssh)) != 0) | 179 | (r = sshpkt_get_end(ssh)) != 0) |
179 | goto out; | 180 | goto out; |
180 | #ifdef DEBUG_KEXDH | 181 | if ((shared_secret = sshbuf_new()) == NULL) { |
181 | fprintf(stderr, "dh_server_pub= "); | ||
182 | BN_print_fp(stderr, dh_server_pub); | ||
183 | fprintf(stderr, "\n"); | ||
184 | debug("bits %d", BN_num_bits(dh_server_pub)); | ||
185 | #endif | ||
186 | if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { | ||
187 | sshpkt_disconnect(ssh, "bad server public DH value"); | ||
188 | r = SSH_ERR_MESSAGE_INCOMPLETE; | ||
189 | goto out; | ||
190 | } | ||
191 | |||
192 | klen = DH_size(kex->dh); | ||
193 | if ((kbuf = malloc(klen)) == NULL || | ||
194 | (shared_secret = BN_new()) == NULL) { | ||
195 | r = SSH_ERR_ALLOC_FAIL; | 182 | r = SSH_ERR_ALLOC_FAIL; |
196 | goto out; | 183 | goto out; |
197 | } | 184 | } |
198 | if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || | 185 | if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) |
199 | BN_bin2bn(kbuf, kout, shared_secret) == NULL) { | ||
200 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
201 | goto out; | 186 | goto out; |
202 | } | ||
203 | #ifdef DEBUG_KEXDH | ||
204 | dump_digest("shared secret", kbuf, kout); | ||
205 | #endif | ||
206 | if (ssh->compat & SSH_OLD_DHGEX) | 187 | if (ssh->compat & SSH_OLD_DHGEX) |
207 | kex->min = kex->max = -1; | 188 | kex->min = kex->max = -1; |
208 | 189 | ||
@@ -221,7 +202,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) | |||
221 | dh_p, dh_g, | 202 | dh_p, dh_g, |
222 | pub_key, | 203 | pub_key, |
223 | dh_server_pub, | 204 | dh_server_pub, |
224 | shared_secret, | 205 | sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), |
225 | hash, &hashlen)) != 0) | 206 | hash, &hashlen)) != 0) |
226 | goto out; | 207 | goto out; |
227 | 208 | ||
@@ -229,18 +210,14 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) | |||
229 | hashlen, kex->hostkey_alg, ssh->compat)) != 0) | 210 | hashlen, kex->hostkey_alg, ssh->compat)) != 0) |
230 | goto out; | 211 | goto out; |
231 | 212 | ||
232 | if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) | 213 | if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) |
233 | r = kex_send_newkeys(ssh); | 214 | r = kex_send_newkeys(ssh); |
234 | out: | 215 | out: |
235 | explicit_bzero(hash, sizeof(hash)); | 216 | explicit_bzero(hash, sizeof(hash)); |
236 | DH_free(kex->dh); | 217 | DH_free(kex->dh); |
237 | kex->dh = NULL; | 218 | kex->dh = NULL; |
238 | BN_clear_free(dh_server_pub); | 219 | BN_clear_free(dh_server_pub); |
239 | if (kbuf) { | 220 | sshbuf_free(shared_secret); |
240 | explicit_bzero(kbuf, klen); | ||
241 | free(kbuf); | ||
242 | } | ||
243 | BN_clear_free(shared_secret); | ||
244 | sshkey_free(server_host_key); | 221 | sshkey_free(server_host_key); |
245 | free(server_host_key_blob); | 222 | free(server_host_key_blob); |
246 | free(signature); | 223 | free(signature); |
@@ -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; |