summaryrefslogtreecommitdiff
path: root/kexdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexdh.c')
-rw-r--r--kexdh.c203
1 files changed, 154 insertions, 49 deletions
diff --git a/kexdh.c b/kexdh.c
index e6925b186..67133e339 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */ 1/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 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,67 +30,172 @@
30#include <sys/types.h> 30#include <sys/types.h>
31 31
32#include <signal.h> 32#include <signal.h>
33 33#include <stdio.h>
34#include <openssl/evp.h> 34#include <string.h>
35 35
36#include "openbsd-compat/openssl-compat.h" 36#include "openbsd-compat/openssl-compat.h"
37#include <openssl/dh.h>
37 38
38#include "ssh2.h"
39#include "sshkey.h" 39#include "sshkey.h"
40#include "cipher.h"
41#include "kex.h" 40#include "kex.h"
42#include "ssherr.h"
43#include "sshbuf.h" 41#include "sshbuf.h"
44#include "digest.h" 42#include "digest.h"
43#include "ssherr.h"
44#include "dh.h"
45 45
46int 46int
47kex_dh_hash( 47kex_dh_keygen(struct kex *kex)
48 int hash_alg,
49 const char *client_version_string,
50 const char *server_version_string,
51 const u_char *ckexinit, size_t ckexinitlen,
52 const u_char *skexinit, size_t skexinitlen,
53 const u_char *serverhostkeyblob, size_t sbloblen,
54 const BIGNUM *client_dh_pub,
55 const BIGNUM *server_dh_pub,
56 const BIGNUM *shared_secret,
57 u_char *hash, size_t *hashlen)
58{ 48{
59 struct sshbuf *b; 49 switch (kex->kex_type) {
60 int r; 50 case KEX_DH_GRP1_SHA1:
61 51 kex->dh = dh_new_group1();
62 if (*hashlen < ssh_digest_bytes(hash_alg)) 52 break;
53 case KEX_DH_GRP14_SHA1:
54 case KEX_DH_GRP14_SHA256:
55 kex->dh = dh_new_group14();
56 break;
57 case KEX_DH_GRP16_SHA512:
58 kex->dh = dh_new_group16();
59 break;
60 case KEX_DH_GRP18_SHA512:
61 kex->dh = dh_new_group18();
62 break;
63 default:
63 return SSH_ERR_INVALID_ARGUMENT; 64 return SSH_ERR_INVALID_ARGUMENT;
64 if ((b = sshbuf_new()) == NULL)
65 return SSH_ERR_ALLOC_FAIL;
66 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
67 (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
68 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
69 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
70 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
71 (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
72 (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
73 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
74 (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
75 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
76 (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
77 (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
78 (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
79 sshbuf_free(b);
80 return r;
81 } 65 }
82#ifdef DEBUG_KEX 66 if (kex->dh == NULL)
83 sshbuf_dump(b, stderr); 67 return SSH_ERR_ALLOC_FAIL;
68 return (dh_gen_key(kex->dh, kex->we_need * 8));
69}
70
71int
72kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
73{
74 BIGNUM *shared_secret = NULL;
75 u_char *kbuf = NULL;
76 size_t klen = 0;
77 int kout, r;
78
79#ifdef DEBUG_KEXDH
80 fprintf(stderr, "dh_pub= ");
81 BN_print_fp(stderr, dh_pub);
82 fprintf(stderr, "\n");
83 debug("bits %d", BN_num_bits(dh_pub));
84 DHparams_print_fp(stderr, kex->dh);
85 fprintf(stderr, "\n");
84#endif 86#endif
85 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { 87
86 sshbuf_free(b); 88 if (!dh_pub_is_valid(kex->dh, dh_pub)) {
87 return SSH_ERR_LIBCRYPTO_ERROR; 89 r = SSH_ERR_MESSAGE_INCOMPLETE;
90 goto out;
91 }
92 klen = DH_size(kex->dh);
93 if ((kbuf = malloc(klen)) == NULL ||
94 (shared_secret = BN_new()) == NULL) {
95 r = SSH_ERR_ALLOC_FAIL;
96 goto out;
97 }
98 if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
99 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
100 r = SSH_ERR_LIBCRYPTO_ERROR;
101 goto out;
88 } 102 }
89 sshbuf_free(b); 103#ifdef DEBUG_KEXDH
90 *hashlen = ssh_digest_bytes(hash_alg); 104 dump_digest("shared secret", kbuf, kout);
91#ifdef DEBUG_KEX
92 dump_digest("hash", hash, *hashlen);
93#endif 105#endif
94 return 0; 106 r = sshbuf_put_bignum2(out, shared_secret);
107 out:
108 freezero(kbuf, klen);
109 BN_clear_free(shared_secret);
110 return r;
111}
112
113int
114kex_dh_keypair(struct kex *kex)
115{
116 const BIGNUM *pub_key;
117 struct sshbuf *buf = NULL;
118 int r;
119
120 if ((r = kex_dh_keygen(kex)) != 0)
121 return r;
122 DH_get0_key(kex->dh, &pub_key, NULL);
123 if ((buf = sshbuf_new()) == NULL)
124 return SSH_ERR_ALLOC_FAIL;
125 if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 ||
126 (r = sshbuf_get_u32(buf, NULL)) != 0)
127 goto out;
128#ifdef DEBUG_KEXDH
129 DHparams_print_fp(stderr, kex->dh);
130 fprintf(stderr, "pub= ");
131 BN_print_fp(stderr, pub_key);
132 fprintf(stderr, "\n");
133#endif
134 kex->client_pub = buf;
135 buf = NULL;
136 out:
137 sshbuf_free(buf);
138 return r;
139}
140
141int
142kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
143 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
144{
145 const BIGNUM *pub_key;
146 struct sshbuf *server_blob = NULL;
147 int r;
148
149 *server_blobp = NULL;
150 *shared_secretp = NULL;
151
152 if ((r = kex_dh_keygen(kex)) != 0)
153 goto out;
154 DH_get0_key(kex->dh, &pub_key, NULL);
155 if ((server_blob = sshbuf_new()) == NULL) {
156 r = SSH_ERR_ALLOC_FAIL;
157 goto out;
158 }
159 if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
160 (r = sshbuf_get_u32(server_blob, NULL)) != 0)
161 goto out;
162 if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
163 goto out;
164 *server_blobp = server_blob;
165 server_blob = NULL;
166 out:
167 DH_free(kex->dh);
168 kex->dh = NULL;
169 sshbuf_free(server_blob);
170 return r;
171}
172
173int
174kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
175 struct sshbuf **shared_secretp)
176{
177 struct sshbuf *buf = NULL;
178 BIGNUM *dh_pub = NULL;
179 int r;
180
181 *shared_secretp = NULL;
182
183 if ((buf = sshbuf_new()) == NULL) {
184 r = SSH_ERR_ALLOC_FAIL;
185 goto out;
186 }
187 if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
188 (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
189 goto out;
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;
95} 200}
96#endif /* WITH_OPENSSL */ 201#endif /* WITH_OPENSSL */