diff options
Diffstat (limited to 'kexdh.c')
-rw-r--r-- | kexdh.c | 140 |
1 files changed, 88 insertions, 52 deletions
@@ -1,6 +1,6 @@ | |||
1 | /* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */ | 1 | /* $OpenBSD: kexdh.c,v 1.30 2019/01/21 10:28:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2019 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | 6 | * modification, are permitted provided that the following conditions |
@@ -30,17 +30,11 @@ | |||
30 | #include <sys/types.h> | 30 | #include <sys/types.h> |
31 | 31 | ||
32 | #include <signal.h> | 32 | #include <signal.h> |
33 | #include <stdio.h> | ||
34 | #include <string.h> | ||
33 | 35 | ||
34 | #include <openssl/evp.h> | ||
35 | |||
36 | #include "openbsd-compat/openssl-compat.h" | ||
37 | |||
38 | #include "ssh2.h" | ||
39 | #include "sshkey.h" | 36 | #include "sshkey.h" |
40 | #include "cipher.h" | ||
41 | #include "kex.h" | 37 | #include "kex.h" |
42 | #include "dh.h" | ||
43 | #include "ssherr.h" | ||
44 | #include "sshbuf.h" | 38 | #include "sshbuf.h" |
45 | #include "digest.h" | 39 | #include "digest.h" |
46 | #include "dh.h" | 40 | #include "dh.h" |
@@ -113,53 +107,95 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) | |||
113 | } | 107 | } |
114 | 108 | ||
115 | int | 109 | int |
116 | kex_dh_hash( | 110 | kex_dh_keypair(struct kex *kex) |
117 | int hash_alg, | ||
118 | const struct sshbuf *client_version, | ||
119 | const struct sshbuf *server_version, | ||
120 | const u_char *ckexinit, size_t ckexinitlen, | ||
121 | const u_char *skexinit, size_t skexinitlen, | ||
122 | const u_char *serverhostkeyblob, size_t sbloblen, | ||
123 | const BIGNUM *client_dh_pub, | ||
124 | const BIGNUM *server_dh_pub, | ||
125 | const u_char *shared_secret, size_t secretlen, | ||
126 | u_char *hash, size_t *hashlen) | ||
127 | { | 111 | { |
128 | struct sshbuf *b; | 112 | const BIGNUM *pub_key; |
113 | struct sshbuf *buf = NULL; | ||
129 | int r; | 114 | int r; |
130 | 115 | ||
131 | if (*hashlen < ssh_digest_bytes(hash_alg)) | 116 | if ((r = kex_dh_keygen(kex)) != 0) |
132 | return SSH_ERR_INVALID_ARGUMENT; | ||
133 | if ((b = sshbuf_new()) == NULL) | ||
134 | return SSH_ERR_ALLOC_FAIL; | ||
135 | if ((r = sshbuf_put_stringb(b, client_version)) < 0 || | ||
136 | (r = sshbuf_put_stringb(b, server_version)) < 0 || | ||
137 | /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ | ||
138 | (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || | ||
139 | (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || | ||
140 | (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || | ||
141 | (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || | ||
142 | (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || | ||
143 | (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || | ||
144 | (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || | ||
145 | (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || | ||
146 | (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || | ||
147 | (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { | ||
148 | sshbuf_free(b); | ||
149 | return r; | 117 | return r; |
150 | } | 118 | DH_get0_key(kex->dh, &pub_key, NULL); |
151 | #ifdef DEBUG_KEX | 119 | if ((buf = sshbuf_new()) == NULL) |
152 | sshbuf_dump(b, stderr); | 120 | return SSH_ERR_ALLOC_FAIL; |
121 | if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 || | ||
122 | (r = sshbuf_get_u32(buf, NULL)) != 0) | ||
123 | goto out; | ||
124 | #ifdef DEBUG_KEXDH | ||
125 | DHparams_print_fp(stderr, kex->dh); | ||
126 | fprintf(stderr, "pub= "); | ||
127 | BN_print_fp(stderr, pub_key); | ||
128 | fprintf(stderr, "\n"); | ||
153 | #endif | 129 | #endif |
154 | if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { | 130 | kex->kem_client_pub = buf; |
155 | sshbuf_free(b); | 131 | buf = NULL; |
156 | return SSH_ERR_LIBCRYPTO_ERROR; | 132 | out: |
133 | sshbuf_free(buf); | ||
134 | return r; | ||
135 | } | ||
136 | |||
137 | int | ||
138 | kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, | ||
139 | struct sshbuf **server_blobp, struct sshbuf **shared_secretp) | ||
140 | { | ||
141 | const BIGNUM *pub_key; | ||
142 | struct sshbuf *server_blob = NULL; | ||
143 | int r; | ||
144 | |||
145 | *server_blobp = NULL; | ||
146 | *shared_secretp = NULL; | ||
147 | |||
148 | if ((r = kex_dh_keygen(kex)) != 0) | ||
149 | goto out; | ||
150 | DH_get0_key(kex->dh, &pub_key, NULL); | ||
151 | if ((server_blob = sshbuf_new()) == NULL) { | ||
152 | r = SSH_ERR_ALLOC_FAIL; | ||
153 | goto out; | ||
157 | } | 154 | } |
158 | sshbuf_free(b); | 155 | if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 || |
159 | *hashlen = ssh_digest_bytes(hash_alg); | 156 | (r = sshbuf_get_u32(server_blob, NULL)) != 0) |
160 | #ifdef DEBUG_KEX | 157 | goto out; |
161 | dump_digest("hash", hash, *hashlen); | 158 | if ((r = kex_dh_dec(kex, pkblob, pklen, shared_secretp)) != 0) |
162 | #endif | 159 | goto out; |
163 | return 0; | 160 | *server_blobp = server_blob; |
161 | server_blob = NULL; | ||
162 | out: | ||
163 | DH_free(kex->dh); | ||
164 | kex->dh = NULL; | ||
165 | sshbuf_free(server_blob); | ||
166 | return r; | ||
167 | } | ||
168 | |||
169 | int | ||
170 | kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, | ||
171 | struct sshbuf **shared_secretp) | ||
172 | { | ||
173 | struct sshbuf *buf = NULL; | ||
174 | BIGNUM *dh_pub = NULL; | ||
175 | int r; | ||
176 | |||
177 | *shared_secretp = NULL; | ||
178 | |||
179 | if ((buf = sshbuf_new()) == NULL) { | ||
180 | r = SSH_ERR_ALLOC_FAIL; | ||
181 | goto out; | ||
182 | } | ||
183 | if ((r = sshbuf_put_u32(buf, pklen)) != 0 || | ||
184 | (r = sshbuf_put(buf, pkblob, pklen)) != 0) { | ||
185 | goto out; | ||
186 | } | ||
187 | if ((r = sshbuf_get_bignum2(buf, &dh_pub)) != 0) { | ||
188 | goto out; | ||
189 | } | ||
190 | sshbuf_reset(buf); | ||
191 | if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0) | ||
192 | goto out; | ||
193 | *shared_secretp = buf; | ||
194 | buf = NULL; | ||
195 | out: | ||
196 | DH_free(kex->dh); | ||
197 | kex->dh = NULL; | ||
198 | sshbuf_free(buf); | ||
199 | return r; | ||
164 | } | 200 | } |
165 | #endif /* WITH_OPENSSL */ | 201 | #endif /* WITH_OPENSSL */ |