Skip to content

Commit 732f044

Browse files
committed
Prototype KEX crypto interface and kexdhc changes based on this interface
1 parent 66426d7 commit 732f044

File tree

6 files changed

+282
-76
lines changed

6 files changed

+282
-76
lines changed

contrib/win32/openssh/libssh.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@
258258
<ClCompile Include="$(OpenSSH-Src-Path)uuencode.c" />
259259
<ClCompile Include="$(OpenSSH-Src-Path)verify.c" />
260260
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c" />
261+
<ClCompile Include="..\..\..\kexdh-openssl.c" />
261262
</ItemGroup>
262263
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
263264
<ImportGroup Label="ExtensionTargets">

contrib/win32/openssh/libssh.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,5 +288,8 @@
288288
<ClCompile Include="$(OpenSSH-Src-Path)xmalloc.c">
289289
<Filter>Source Files</Filter>
290290
</ClCompile>
291+
<ClCompile Include="..\..\..\kexdh-openssl.c">
292+
<Filter>Source Files</Filter>
293+
</ClCompile>
291294
</ItemGroup>
292295
</Project>

kex.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,26 @@ struct newkeys {
121121

122122
struct ssh;
123123

124+
//KEX DH interface start
125+
struct sshbuf;
126+
typedef struct kexdhi_
127+
{
128+
//consume p and g from "in"
129+
int(*read_p_g)(struct kexdhi_*, struct sshbuf* in);
130+
//encode p and g in "out"
131+
int(*get_p_g)(struct kexdhi_*, struct sshbuf* out);
132+
//encode public key in pub
133+
int(*get_pub_key)(struct kexdhi_*, struct sshbuf* pub);
134+
//read other public key from other_pub and encode secretagreement in secret
135+
int(*get_secret)(struct kexdhi_*, struct sshbuf* other_pub, struct sshbuf* secret);
136+
void(*done)(struct kexdhi_*);
137+
}kexdhi;
138+
139+
kexdhi* kexdh_openssl_init(struct ssh* ssh);
140+
//KEX DH interface end
141+
142+
143+
124144
struct kex {
125145
u_char *session_id;
126146
size_t session_id_len;
@@ -150,6 +170,8 @@ struct kex {
150170
u_char **, size_t *, const u_char *, size_t, u_int);
151171
int (*kex[KEX_MAX])(struct ssh *);
152172
/* kex specific state */
173+
kexdhi* kexdh;
174+
153175
DH *dh; /* DH */
154176
u_int min, max, nbits; /* GEX */
155177
EC_KEY *ec_client_key; /* ECDH */
@@ -191,6 +213,12 @@ int kex_dh_hash(const char *, const char *,
191213
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
192214
const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
193215

216+
//version of kex_dh_hash with public keys and secret passed as sshbuf instead of BIGNUM
217+
int kex_dh_hash_(
218+
const char *, const char *, const u_char *, size_t , const u_char *, size_t ,
219+
const u_char *, size_t , const struct sshbuf *, const struct sshbuf *, const struct sshbuf *,
220+
u_char *hash, size_t *);
221+
194222
int kexgex_hash(int, const char *, const char *,
195223
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
196224
int, int, int,

kexdh-openssl.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#include "includes.h"
2+
3+
#ifdef WITH_OPENSSL
4+
5+
#include <openssl/dh.h>
6+
7+
#include <stdarg.h>
8+
#include <stdio.h>
9+
10+
#include "kex.h"
11+
#include "log.h"
12+
#include "packet.h"
13+
#include "dh.h"
14+
#include "ssh2.h"
15+
#include "dispatch.h"
16+
#include "compat.h"
17+
#include "ssherr.h"
18+
#include "sshbuf.h"
19+
20+
typedef struct kexdh_openssl_
21+
{
22+
kexdhi dhi;
23+
struct ssh* ssh;
24+
DH* dh;
25+
}kexdh_openssl;
26+
27+
28+
static int kexdh_get_pub_key(kexdhi* dh_, struct sshbuf* pub)
29+
{
30+
int r = 0;
31+
kexdh_openssl* dh = (kexdh_openssl*)dh_;
32+
struct kex* kex = dh->ssh->kex;
33+
34+
/* generate and send 'e', client DH public key */
35+
switch (kex->kex_type) {
36+
case KEX_DH_GRP1_SHA1:
37+
dh->dh = dh_new_group1();
38+
break;
39+
case KEX_DH_GRP14_SHA1:
40+
dh->dh = dh_new_group14();
41+
break;
42+
default:
43+
r = SSH_ERR_INVALID_ARGUMENT;
44+
goto out;
45+
}
46+
47+
if ((r = dh_gen_key(dh->dh, kex->we_need * 8)) != 0 ||
48+
(r = sshpkt_put_bignum2(pub, dh->dh->pub_key)) != 0)
49+
goto out;
50+
#ifdef DEBUG_KEXDH
51+
DHparams_print_fp(stderr, dh->dh);
52+
fprintf(stderr, "pub= ");
53+
BN_print_fp(stderr, dh->dh->pub_key);
54+
fprintf(stderr, "\n");
55+
#endif
56+
return 0;
57+
out:
58+
return r;
59+
}
60+
61+
static int kexdh_get_secret(kexdhi* dh_, struct sshbuf* other_pub, struct sshbuf* secret)
62+
{
63+
int r = 0, kout;
64+
BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
65+
kexdh_openssl* dh = (kexdh_openssl*)dh_;
66+
struct kex* kex = dh->ssh->kex;
67+
size_t klen = 0;
68+
u_char *kbuf = NULL;
69+
70+
/* DH parameter f, server public DH key */
71+
if ((dh_server_pub = BN_new()) == NULL) {
72+
r = SSH_ERR_ALLOC_FAIL;
73+
goto out;
74+
}
75+
76+
if ((r = sshbuf_get_bignum2(other_pub, dh_server_pub)) != 0) {
77+
goto out;
78+
}
79+
80+
#ifdef DEBUG_KEXDH
81+
fprintf(stderr, "dh_server_pub= ");
82+
BN_print_fp(stderr, dh_server_pub);
83+
fprintf(stderr, "\n");
84+
debug("bits %d", BN_num_bits(dh_server_pub));
85+
#endif
86+
if (!dh_pub_is_valid(dh->dh, dh_server_pub)) {
87+
sshpkt_disconnect(dh->ssh, "bad server public DH value");
88+
r = SSH_ERR_MESSAGE_INCOMPLETE;
89+
goto out;
90+
}
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_server_pub, kex->dh)) < 0 ||
99+
BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
100+
r = SSH_ERR_LIBCRYPTO_ERROR;
101+
goto out;
102+
}
103+
#ifdef DEBUG_KEXDH
104+
dump_digest("shared secret", kbuf, kout);
105+
#endif
106+
107+
if ((r == sshbuf_put_bignum2(secret, shared_secret)) != 0) {
108+
goto out;
109+
}
110+
out:
111+
if (dh_server_pub)
112+
BN_clear_free(dh_server_pub);
113+
if (kbuf) {
114+
explicit_bzero(kbuf, klen);
115+
free(kbuf);
116+
}
117+
if (shared_secret)
118+
BN_clear_free(shared_secret);
119+
120+
return r;
121+
}
122+
123+
static void kexdh_done(kexdhi* dh_)
124+
{
125+
kexdh_openssl* dh = (kexdh_openssl*)dh_;
126+
127+
if (dh->dh)
128+
DH_free(dh->dh);
129+
free(dh_);
130+
}
131+
132+
133+
kexdhi* kexdh_openssl_init(struct ssh* ssh)
134+
{
135+
136+
kexdh_openssl *dh = malloc(sizeof(kexdh_openssl));
137+
138+
if (dh)
139+
{
140+
dh->ssh = ssh;
141+
dh->dhi.get_pub_key = kexdh_get_pub_key;
142+
dh->dhi.get_secret = kexdh_get_secret;
143+
dh->dhi.done = kexdh_done;
144+
dh->dhi.get_p_g = NULL;
145+
dh->dhi.read_p_g = NULL;
146+
}
147+
148+
return dh;
149+
}
150+
151+
152+
#endif

kexdh.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,52 @@ kex_dh_hash(
9090
#endif
9191
return 0;
9292
}
93+
kex_dh_hash_(
94+
const char *client_version_string,
95+
const char *server_version_string,
96+
const u_char *ckexinit, size_t ckexinitlen,
97+
const u_char *skexinit, size_t skexinitlen,
98+
const u_char *serverhostkeyblob, size_t sbloblen,
99+
const struct sshbuf *client_dh_pub,
100+
const struct sshbuf *server_dh_pub,
101+
const struct sshbuf *shared_secret,
102+
u_char *hash, size_t *hashlen)
103+
{
104+
struct sshbuf *b;
105+
int r;
106+
107+
if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1))
108+
return SSH_ERR_INVALID_ARGUMENT;
109+
if ((b = sshbuf_new()) == NULL)
110+
return SSH_ERR_ALLOC_FAIL;
111+
if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
112+
(r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
113+
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
114+
(r = sshbuf_put_u32(b, ckexinitlen + 1)) != 0 ||
115+
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
116+
(r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
117+
(r = sshbuf_put_u32(b, skexinitlen + 1)) != 0 ||
118+
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
119+
(r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
120+
(r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
121+
(r = sshbuf_put_b(b, client_dh_pub)) != 0 ||
122+
(r = sshbuf_put_b(b, server_dh_pub)) != 0 ||
123+
(r = sshbuf_put_b(b, shared_secret)) != 0) {
124+
sshbuf_free(b);
125+
return r;
126+
}
127+
#ifdef DEBUG_KEX
128+
sshbuf_dump(b, stderr);
129+
#endif
130+
if (ssh_digest_buffer(SSH_DIGEST_SHA1, b, hash, *hashlen) != 0) {
131+
sshbuf_free(b);
132+
return SSH_ERR_LIBCRYPTO_ERROR;
133+
}
134+
sshbuf_free(b);
135+
*hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
136+
#ifdef DEBUG_KEX
137+
dump_digest("hash", hash, *hashlen);
138+
#endif
139+
return 0;
140+
}
93141
#endif /* WITH_OPENSSL */

0 commit comments

Comments
 (0)