summaryrefslogtreecommitdiff
path: root/kexdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexdh.c')
-rw-r--r--kexdh.c140
1 files changed, 88 insertions, 52 deletions
diff --git a/kexdh.c b/kexdh.c
index 5324857b2..4b811b617 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -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
115int 109int
116kex_dh_hash( 110kex_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
137int
138kex_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
169int
170kex_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 */