11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: kexecdhs.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2001 Markus Friedl.  All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2010 Damien Miller.  All rights reserved.
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h"
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dh.h"
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "monitor_wrap.h"
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/ecdh.h>
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkexecdh_server(Kex *kex)
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT *client_public;
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_KEY *server_key;
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const EC_GROUP *group;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *shared_secret;
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *server_host_private, *server_host_public;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *server_host_key_blob = NULL, *signature = NULL;
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *kbuf, *hash;
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int klen, slen, sbloblen, hashlen;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int curve_nid;
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (EC_KEY_generate_key(server_key) != 1)
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_KEY_generate_key failed", __func__);
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	group = EC_KEY_get0_group(server_key);
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_KEXECDH
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("server private key:\n", stderr);
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_dump_ec_key(server_key);
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kex->load_host_public_key == NULL ||
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    kex->load_host_private_key == NULL)
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Cannot load hostkey");
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	server_host_public = kex->load_host_public_key(kex->hostkey_type);
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (server_host_public == NULL)
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Unsupported hostkey type %d", kex->hostkey_type);
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	server_host_private = kex->load_host_private_key(kex->hostkey_type);
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (server_host_private == NULL)
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Missing private key for hostkey type %d",
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    kex->hostkey_type);
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("expecting SSH2_MSG_KEX_ECDH_INIT");
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_read_expect(SSH2_MSG_KEX_ECDH_INIT);
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((client_public = EC_POINT_new(group)) == NULL)
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: EC_POINT_new failed", __func__);
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_ecpoint(group, client_public);
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_ec_validate_public(group, client_public) != 0)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: invalid client public key", __func__);
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_KEXECDH
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fputs("client public key:\n", stderr);
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_dump_ec_point(group, client_public);
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Calculate shared_secret */
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	klen = (EC_GROUP_get_degree(group) + 7) / 8;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kbuf = xmalloc(klen);
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ECDH_compute_key(kbuf, klen, client_public,
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    server_key, NULL) != (int)klen)
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: ECDH_compute_key failed", __func__);
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_KEXDH
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dump_digest("shared secret", kbuf, klen);
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((shared_secret = BN_new()) == NULL)
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new failed", __func__);
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_bin2bn failed", __func__);
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(kbuf, 0, klen);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(kbuf);
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* calc H */
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex_ecdh_hash(
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    kex->evp_md,
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    group,
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    kex->client_version_string,
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    kex->server_version_string,
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&kex->my), buffer_len(&kex->my),
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    server_host_key_blob, sbloblen,
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    client_public,
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    EC_KEY_get0_public_key(server_key),
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    shared_secret,
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &hash, &hashlen
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	);
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT_clear_free(client_public);
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* save session id := H */
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kex->session_id == NULL) {
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		kex->session_id_len = hashlen;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		kex->session_id = xmalloc(kex->session_id_len);
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(kex->session_id, hash, kex->session_id_len);
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* sign H */
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (PRIVSEP(key_sign(server_host_private, &signature, &slen,
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    hash, hashlen)) < 0)
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("kexdh_server: key_sign failed");
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* destroy_sensitive_data(); */
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_KEX_ECDH_REPLY);
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(server_host_key_blob, sbloblen);
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key));
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(signature, slen);
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(signature);
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(server_host_key_blob);
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* have keys, free server key */
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_KEY_free(server_key);
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex_derive_keys(kex, hash, hashlen, shared_secret);
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_clear_free(shared_secret);
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex_finish(kex);
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* OPENSSL_HAS_ECC */
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkexecdh_server(Kex *kex)
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fatal("ECC support is not enabled");
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
174