1295367Sdes/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
2218767Sdes/*
3218767Sdes * Copyright (c) 2001 Markus Friedl.  All rights reserved.
4218767Sdes * Copyright (c) 2010 Damien Miller.  All rights reserved.
5218767Sdes *
6218767Sdes * Redistribution and use in source and binary forms, with or without
7218767Sdes * modification, are permitted provided that the following conditions
8218767Sdes * are met:
9218767Sdes * 1. Redistributions of source code must retain the above copyright
10218767Sdes *    notice, this list of conditions and the following disclaimer.
11218767Sdes * 2. Redistributions in binary form must reproduce the above copyright
12218767Sdes *    notice, this list of conditions and the following disclaimer in the
13218767Sdes *    documentation and/or other materials provided with the distribution.
14218767Sdes *
15218767Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16218767Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17218767Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18218767Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19218767Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20218767Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21218767Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22218767Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23218767Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24218767Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25218767Sdes */
26218767Sdes
27218767Sdes#include "includes.h"
28218767Sdes
29295367Sdes#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
30218767Sdes
31218767Sdes#include <sys/types.h>
32218767Sdes
33218767Sdes#include <signal.h>
34218767Sdes#include <string.h>
35218767Sdes
36218767Sdes#include <openssl/bn.h>
37218767Sdes#include <openssl/evp.h>
38218767Sdes#include <openssl/ec.h>
39218767Sdes#include <openssl/ecdh.h>
40218767Sdes
41218767Sdes#include "ssh2.h"
42295367Sdes#include "sshkey.h"
43218767Sdes#include "cipher.h"
44218767Sdes#include "kex.h"
45295367Sdes#include "sshbuf.h"
46262566Sdes#include "digest.h"
47295367Sdes#include "ssherr.h"
48218767Sdes
49295367Sdesint
50218767Sdeskex_ecdh_hash(
51262566Sdes    int hash_alg,
52218767Sdes    const EC_GROUP *ec_group,
53295367Sdes    const char *client_version_string,
54295367Sdes    const char *server_version_string,
55295367Sdes    const u_char *ckexinit, size_t ckexinitlen,
56295367Sdes    const u_char *skexinit, size_t skexinitlen,
57295367Sdes    const u_char *serverhostkeyblob, size_t sbloblen,
58218767Sdes    const EC_POINT *client_dh_pub,
59218767Sdes    const EC_POINT *server_dh_pub,
60218767Sdes    const BIGNUM *shared_secret,
61295367Sdes    u_char *hash, size_t *hashlen)
62218767Sdes{
63295367Sdes	struct sshbuf *b;
64295367Sdes	int r;
65218767Sdes
66295367Sdes	if (*hashlen < ssh_digest_bytes(hash_alg))
67295367Sdes		return SSH_ERR_INVALID_ARGUMENT;
68295367Sdes	if ((b = sshbuf_new()) == NULL)
69295367Sdes		return SSH_ERR_ALLOC_FAIL;
70295367Sdes	if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
71295367Sdes	    (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
72295367Sdes	    /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
73295367Sdes	    (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
74295367Sdes	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
75295367Sdes	    (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
76295367Sdes	    (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
77295367Sdes	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
78295367Sdes	    (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
79295367Sdes	    (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
80295367Sdes	    (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 ||
81295367Sdes	    (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 ||
82295367Sdes	    (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
83295367Sdes		sshbuf_free(b);
84295367Sdes		return r;
85295367Sdes	}
86218767Sdes#ifdef DEBUG_KEX
87295367Sdes	sshbuf_dump(b, stderr);
88218767Sdes#endif
89295367Sdes	if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
90295367Sdes		sshbuf_free(b);
91295367Sdes		return SSH_ERR_LIBCRYPTO_ERROR;
92295367Sdes	}
93295367Sdes	sshbuf_free(b);
94295367Sdes	*hashlen = ssh_digest_bytes(hash_alg);
95218767Sdes#ifdef DEBUG_KEX
96295367Sdes	dump_digest("hash", hash, *hashlen);
97218767Sdes#endif
98295367Sdes	return 0;
99218767Sdes}
100295367Sdes#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
101