xref: /freebsd-src/crypto/openssh/kexecdh.c (revision 19261079b74319502c6ffa1249920079f0f69a72)
1*19261079SEd Maste /* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */
24a421b63SDag-Erling Smørgrav /*
34a421b63SDag-Erling Smørgrav  * Copyright (c) 2010 Damien Miller.  All rights reserved.
4*19261079SEd Maste  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
54a421b63SDag-Erling Smørgrav  *
64a421b63SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
74a421b63SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
84a421b63SDag-Erling Smørgrav  * are met:
94a421b63SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
104a421b63SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
114a421b63SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
124a421b63SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
134a421b63SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
144a421b63SDag-Erling Smørgrav  *
154a421b63SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
164a421b63SDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
174a421b63SDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
184a421b63SDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
194a421b63SDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
204a421b63SDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
214a421b63SDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
224a421b63SDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
234a421b63SDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
244a421b63SDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
254a421b63SDag-Erling Smørgrav  */
264a421b63SDag-Erling Smørgrav 
274a421b63SDag-Erling Smørgrav #include "includes.h"
284a421b63SDag-Erling Smørgrav 
29bc5531deSDag-Erling Smørgrav #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
304a421b63SDag-Erling Smørgrav 
314a421b63SDag-Erling Smørgrav #include <sys/types.h>
324a421b63SDag-Erling Smørgrav 
33*19261079SEd Maste #include <stdio.h>
344a421b63SDag-Erling Smørgrav #include <string.h>
35*19261079SEd Maste #include <signal.h>
364a421b63SDag-Erling Smørgrav 
374a421b63SDag-Erling Smørgrav #include <openssl/ecdh.h>
384a421b63SDag-Erling Smørgrav 
39bc5531deSDag-Erling Smørgrav #include "sshkey.h"
404a421b63SDag-Erling Smørgrav #include "kex.h"
41bc5531deSDag-Erling Smørgrav #include "sshbuf.h"
42f7167e0eSDag-Erling Smørgrav #include "digest.h"
43bc5531deSDag-Erling Smørgrav #include "ssherr.h"
444a421b63SDag-Erling Smørgrav 
45*19261079SEd Maste static int
46*19261079SEd Maste kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
47*19261079SEd Maste     const EC_GROUP *, struct sshbuf **);
48*19261079SEd Maste 
49bc5531deSDag-Erling Smørgrav int
kex_ecdh_keypair(struct kex * kex)50*19261079SEd Maste kex_ecdh_keypair(struct kex *kex)
514a421b63SDag-Erling Smørgrav {
52*19261079SEd Maste 	EC_KEY *client_key = NULL;
53*19261079SEd Maste 	const EC_GROUP *group;
54*19261079SEd Maste 	const EC_POINT *public_key;
55*19261079SEd Maste 	struct sshbuf *buf = NULL;
56bc5531deSDag-Erling Smørgrav 	int r;
574a421b63SDag-Erling Smørgrav 
58*19261079SEd Maste 	if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
59*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
60*19261079SEd Maste 		goto out;
61*19261079SEd Maste 	}
62*19261079SEd Maste 	if (EC_KEY_generate_key(client_key) != 1) {
63*19261079SEd Maste 		r = SSH_ERR_LIBCRYPTO_ERROR;
64*19261079SEd Maste 		goto out;
65*19261079SEd Maste 	}
66*19261079SEd Maste 	group = EC_KEY_get0_group(client_key);
67*19261079SEd Maste 	public_key = EC_KEY_get0_public_key(client_key);
68*19261079SEd Maste 
69*19261079SEd Maste 	if ((buf = sshbuf_new()) == NULL) {
70*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
71*19261079SEd Maste 		goto out;
72*19261079SEd Maste 	}
73*19261079SEd Maste 	if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 ||
74*19261079SEd Maste 	    (r = sshbuf_get_u32(buf, NULL)) != 0)
75*19261079SEd Maste 		goto out;
76*19261079SEd Maste #ifdef DEBUG_KEXECDH
77*19261079SEd Maste 	fputs("client private key:\n", stderr);
78*19261079SEd Maste 	sshkey_dump_ec_key(client_key);
79*19261079SEd Maste #endif
80*19261079SEd Maste 	kex->ec_client_key = client_key;
81*19261079SEd Maste 	kex->ec_group = group;
82*19261079SEd Maste 	client_key = NULL;	/* owned by the kex */
83*19261079SEd Maste 	kex->client_pub = buf;
84*19261079SEd Maste 	buf = NULL;
85*19261079SEd Maste  out:
86*19261079SEd Maste 	EC_KEY_free(client_key);
87*19261079SEd Maste 	sshbuf_free(buf);
88bc5531deSDag-Erling Smørgrav 	return r;
894a421b63SDag-Erling Smørgrav }
90*19261079SEd Maste 
91*19261079SEd Maste int
kex_ecdh_enc(struct kex * kex,const struct sshbuf * client_blob,struct sshbuf ** server_blobp,struct sshbuf ** shared_secretp)92*19261079SEd Maste kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
93*19261079SEd Maste     struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
94*19261079SEd Maste {
95*19261079SEd Maste 	const EC_GROUP *group;
96*19261079SEd Maste 	const EC_POINT *pub_key;
97*19261079SEd Maste 	EC_KEY *server_key = NULL;
98*19261079SEd Maste 	struct sshbuf *server_blob = NULL;
99*19261079SEd Maste 	int r;
100*19261079SEd Maste 
101*19261079SEd Maste 	*server_blobp = NULL;
102*19261079SEd Maste 	*shared_secretp = NULL;
103*19261079SEd Maste 
104*19261079SEd Maste 	if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
105*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
106*19261079SEd Maste 		goto out;
107bc5531deSDag-Erling Smørgrav 	}
108*19261079SEd Maste 	if (EC_KEY_generate_key(server_key) != 1) {
109*19261079SEd Maste 		r = SSH_ERR_LIBCRYPTO_ERROR;
110*19261079SEd Maste 		goto out;
111*19261079SEd Maste 	}
112*19261079SEd Maste 	group = EC_KEY_get0_group(server_key);
113*19261079SEd Maste 
114*19261079SEd Maste #ifdef DEBUG_KEXECDH
115*19261079SEd Maste 	fputs("server private key:\n", stderr);
116*19261079SEd Maste 	sshkey_dump_ec_key(server_key);
117bc5531deSDag-Erling Smørgrav #endif
118*19261079SEd Maste 	pub_key = EC_KEY_get0_public_key(server_key);
119*19261079SEd Maste 	if ((server_blob = sshbuf_new()) == NULL) {
120*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
121*19261079SEd Maste 		goto out;
122*19261079SEd Maste 	}
123*19261079SEd Maste 	if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
124*19261079SEd Maste 	    (r = sshbuf_get_u32(server_blob, NULL)) != 0)
125*19261079SEd Maste 		goto out;
126*19261079SEd Maste 	if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group,
127*19261079SEd Maste 	    shared_secretp)) != 0)
128*19261079SEd Maste 		goto out;
129*19261079SEd Maste 	*server_blobp = server_blob;
130*19261079SEd Maste 	server_blob = NULL;
131*19261079SEd Maste  out:
132*19261079SEd Maste 	EC_KEY_free(server_key);
133*19261079SEd Maste 	sshbuf_free(server_blob);
134*19261079SEd Maste 	return r;
135*19261079SEd Maste }
136*19261079SEd Maste 
137*19261079SEd Maste static int
kex_ecdh_dec_key_group(struct kex * kex,const struct sshbuf * ec_blob,EC_KEY * key,const EC_GROUP * group,struct sshbuf ** shared_secretp)138*19261079SEd Maste kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
139*19261079SEd Maste     EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
140*19261079SEd Maste {
141*19261079SEd Maste 	struct sshbuf *buf = NULL;
142*19261079SEd Maste 	BIGNUM *shared_secret = NULL;
143*19261079SEd Maste 	EC_POINT *dh_pub = NULL;
144*19261079SEd Maste 	u_char *kbuf = NULL;
145*19261079SEd Maste 	size_t klen = 0;
146*19261079SEd Maste 	int r;
147*19261079SEd Maste 
148*19261079SEd Maste 	*shared_secretp = NULL;
149*19261079SEd Maste 
150*19261079SEd Maste 	if ((buf = sshbuf_new()) == NULL) {
151*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
152*19261079SEd Maste 		goto out;
153*19261079SEd Maste 	}
154*19261079SEd Maste 	if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
155*19261079SEd Maste 		goto out;
156*19261079SEd Maste 	if ((dh_pub = EC_POINT_new(group)) == NULL) {
157*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
158*19261079SEd Maste 		goto out;
159*19261079SEd Maste 	}
160*19261079SEd Maste 	if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
161*19261079SEd Maste 		goto out;
162*19261079SEd Maste 	}
163*19261079SEd Maste 	sshbuf_reset(buf);
164*19261079SEd Maste 
165*19261079SEd Maste #ifdef DEBUG_KEXECDH
166*19261079SEd Maste 	fputs("public key:\n", stderr);
167*19261079SEd Maste 	sshkey_dump_ec_point(group, dh_pub);
168*19261079SEd Maste #endif
169*19261079SEd Maste 	if (sshkey_ec_validate_public(group, dh_pub) != 0) {
170*19261079SEd Maste 		r = SSH_ERR_MESSAGE_INCOMPLETE;
171*19261079SEd Maste 		goto out;
172*19261079SEd Maste 	}
173*19261079SEd Maste 	klen = (EC_GROUP_get_degree(group) + 7) / 8;
174*19261079SEd Maste 	if ((kbuf = malloc(klen)) == NULL ||
175*19261079SEd Maste 	    (shared_secret = BN_new()) == NULL) {
176*19261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
177*19261079SEd Maste 		goto out;
178*19261079SEd Maste 	}
179*19261079SEd Maste 	if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
180*19261079SEd Maste 	    BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
181*19261079SEd Maste 		r = SSH_ERR_LIBCRYPTO_ERROR;
182*19261079SEd Maste 		goto out;
183*19261079SEd Maste 	}
184*19261079SEd Maste #ifdef DEBUG_KEXECDH
185*19261079SEd Maste 	dump_digest("shared secret", kbuf, klen);
186*19261079SEd Maste #endif
187*19261079SEd Maste 	if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
188*19261079SEd Maste 		goto out;
189*19261079SEd Maste 	*shared_secretp = buf;
190*19261079SEd Maste 	buf = NULL;
191*19261079SEd Maste  out:
192*19261079SEd Maste 	EC_POINT_clear_free(dh_pub);
193*19261079SEd Maste 	BN_clear_free(shared_secret);
194*19261079SEd Maste 	freezero(kbuf, klen);
195*19261079SEd Maste 	sshbuf_free(buf);
196*19261079SEd Maste 	return r;
197*19261079SEd Maste }
198*19261079SEd Maste 
199*19261079SEd Maste int
kex_ecdh_dec(struct kex * kex,const struct sshbuf * server_blob,struct sshbuf ** shared_secretp)200*19261079SEd Maste kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
201*19261079SEd Maste     struct sshbuf **shared_secretp)
202*19261079SEd Maste {
203*19261079SEd Maste 	int r;
204*19261079SEd Maste 
205*19261079SEd Maste 	r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key,
206*19261079SEd Maste 	    kex->ec_group, shared_secretp);
207*19261079SEd Maste 	EC_KEY_free(kex->ec_client_key);
208*19261079SEd Maste 	kex->ec_client_key = NULL;
209*19261079SEd Maste 	return r;
210*19261079SEd Maste }
211*19261079SEd Maste 
212*19261079SEd Maste #else
213*19261079SEd Maste 
214*19261079SEd Maste #include "ssherr.h"
215*19261079SEd Maste 
216*19261079SEd Maste struct kex;
217*19261079SEd Maste struct sshbuf;
218*19261079SEd Maste struct sshkey;
219*19261079SEd Maste 
220*19261079SEd Maste int
kex_ecdh_keypair(struct kex * kex)221*19261079SEd Maste kex_ecdh_keypair(struct kex *kex)
222*19261079SEd Maste {
223*19261079SEd Maste 	return SSH_ERR_SIGN_ALG_UNSUPPORTED;
224*19261079SEd Maste }
225*19261079SEd Maste 
226*19261079SEd Maste int
kex_ecdh_enc(struct kex * kex,const struct sshbuf * client_blob,struct sshbuf ** server_blobp,struct sshbuf ** shared_secretp)227*19261079SEd Maste kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
228*19261079SEd Maste     struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
229*19261079SEd Maste {
230*19261079SEd Maste 	return SSH_ERR_SIGN_ALG_UNSUPPORTED;
231*19261079SEd Maste }
232*19261079SEd Maste 
233*19261079SEd Maste int
kex_ecdh_dec(struct kex * kex,const struct sshbuf * server_blob,struct sshbuf ** shared_secretp)234*19261079SEd Maste kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
235*19261079SEd Maste     struct sshbuf **shared_secretp)
236*19261079SEd Maste {
237*19261079SEd Maste 	return SSH_ERR_SIGN_ALG_UNSUPPORTED;
238bc5531deSDag-Erling Smørgrav }
239bc5531deSDag-Erling Smørgrav #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
240