kexecdhs.c revision 255767
1250881Sjkim/* $OpenBSD: kexecdhs.c,v 1.5 2013/07/19 07:37:48 markus Exp $ */ 2250881Sjkim/* 350488Speter * Copyright (c) 2001 Markus Friedl. All rights reserved. 416514Snate * Copyright (c) 2010 Damien Miller. All rights reserved. 5250881Sjkim * 6250881Sjkim * Redistribution and use in source and binary forms, with or without 7250881Sjkim * modification, are permitted provided that the following conditions 8250881Sjkim * are met: 916514Snate * 1. Redistributions of source code must retain the above copyright 10250881Sjkim * notice, this list of conditions and the following disclaimer. 11250881Sjkim * 2. Redistributions in binary form must reproduce the above copyright 1216514Snate * notice, this list of conditions and the following disclaimer in the 13250881Sjkim * documentation and/or other materials provided with the distribution. 14250881Sjkim * 15250881Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1616514Snate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17250881Sjkim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18250881Sjkim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19250881Sjkim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20250881Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21250881Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22250881Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23250881Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24250881Sjkim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25250881Sjkim */ 26250881Sjkim 27250881Sjkim#include "includes.h" 28250881Sjkim 29250881Sjkim#include <sys/types.h> 30250881Sjkim#include <string.h> 31250881Sjkim#include <signal.h> 32250881Sjkim 33250881Sjkim#include "xmalloc.h" 34250881Sjkim#include "buffer.h" 35250881Sjkim#include "key.h" 36250881Sjkim#include "cipher.h" 37250881Sjkim#include "kex.h" 38250881Sjkim#include "log.h" 39250881Sjkim#include "packet.h" 40250881Sjkim#include "dh.h" 41250881Sjkim#include "ssh2.h" 42250881Sjkim#ifdef GSSAPI 43250881Sjkim#include "ssh-gss.h" 44250881Sjkim#endif 45250881Sjkim#include "monitor_wrap.h" 46250881Sjkim 47250881Sjkim#ifdef OPENSSL_HAS_ECC 48250881Sjkim 49250881Sjkim#include <openssl/ecdh.h> 50250881Sjkim 51250881Sjkimvoid 52250881Sjkimkexecdh_server(Kex *kex) 53250881Sjkim{ 54250881Sjkim EC_POINT *client_public; 55250881Sjkim EC_KEY *server_key; 56250881Sjkim const EC_GROUP *group; 57250881Sjkim BIGNUM *shared_secret; 58250881Sjkim Key *server_host_private, *server_host_public; 59250881Sjkim u_char *server_host_key_blob = NULL, *signature = NULL; 60250881Sjkim u_char *kbuf, *hash; 61250881Sjkim u_int klen, slen, sbloblen, hashlen; 62250881Sjkim 63250881Sjkim if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) 64250881Sjkim fatal("%s: EC_KEY_new_by_curve_name failed", __func__); 65250881Sjkim if (EC_KEY_generate_key(server_key) != 1) 6616514Snate fatal("%s: EC_KEY_generate_key failed", __func__); 6716514Snate group = EC_KEY_get0_group(server_key); 68250881Sjkim 69250881Sjkim#ifdef DEBUG_KEXECDH 70250881Sjkim fputs("server private key:\n", stderr); 71250881Sjkim key_dump_ec_key(server_key); 72250881Sjkim#endif 73250881Sjkim 74250881Sjkim if (kex->load_host_public_key == NULL || 75250881Sjkim kex->load_host_private_key == NULL) 76250881Sjkim fatal("Cannot load hostkey"); 77250881Sjkim server_host_public = kex->load_host_public_key(kex->hostkey_type); 78250881Sjkim if (server_host_public == NULL) 79250881Sjkim fatal("Unsupported hostkey type %d", kex->hostkey_type); 80250881Sjkim server_host_private = kex->load_host_private_key(kex->hostkey_type); 81250881Sjkim 82250881Sjkim debug("expecting SSH2_MSG_KEX_ECDH_INIT"); 83250881Sjkim packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); 84250881Sjkim if ((client_public = EC_POINT_new(group)) == NULL) 85250881Sjkim fatal("%s: EC_POINT_new failed", __func__); 86250881Sjkim packet_get_ecpoint(group, client_public); 87250881Sjkim packet_check_eom(); 88250881Sjkim 89250881Sjkim if (key_ec_validate_public(group, client_public) != 0) 90250881Sjkim fatal("%s: invalid client public key", __func__); 91250881Sjkim 92250881Sjkim#ifdef DEBUG_KEXECDH 93250881Sjkim fputs("client public key:\n", stderr); 94250881Sjkim key_dump_ec_point(group, client_public); 95250881Sjkim#endif 96250881Sjkim 97250881Sjkim /* Calculate shared_secret */ 98250881Sjkim klen = (EC_GROUP_get_degree(group) + 7) / 8; 99250881Sjkim kbuf = xmalloc(klen); 100250881Sjkim if (ECDH_compute_key(kbuf, klen, client_public, 101250881Sjkim server_key, NULL) != (int)klen) 102250881Sjkim fatal("%s: ECDH_compute_key failed", __func__); 103250881Sjkim 104250881Sjkim#ifdef DEBUG_KEXDH 105250881Sjkim dump_digest("shared secret", kbuf, klen); 106250881Sjkim#endif 107250881Sjkim if ((shared_secret = BN_new()) == NULL) 108250881Sjkim fatal("%s: BN_new failed", __func__); 109250881Sjkim if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) 110250881Sjkim fatal("%s: BN_bin2bn failed", __func__); 111250881Sjkim memset(kbuf, 0, klen); 112250881Sjkim free(kbuf); 113250881Sjkim 114250881Sjkim /* calc H */ 11516514Snate key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); 11616514Snate kex_ecdh_hash( 117250881Sjkim kex->evp_md, 118250881Sjkim group, 119250881Sjkim kex->client_version_string, 120250881Sjkim kex->server_version_string, 121250881Sjkim buffer_ptr(&kex->peer), buffer_len(&kex->peer), 122250881Sjkim buffer_ptr(&kex->my), buffer_len(&kex->my), 123250881Sjkim server_host_key_blob, sbloblen, 12416514Snate client_public, 12516514Snate EC_KEY_get0_public_key(server_key), 126250881Sjkim shared_secret, 127250881Sjkim &hash, &hashlen 12816514Snate ); 129250881Sjkim EC_POINT_clear_free(client_public); 130250881Sjkim 131250881Sjkim /* save session id := H */ 132250881Sjkim if (kex->session_id == NULL) { 133250881Sjkim kex->session_id_len = hashlen; 134250881Sjkim kex->session_id = xmalloc(kex->session_id_len); 135250881Sjkim memcpy(kex->session_id, hash, kex->session_id_len); 136250881Sjkim } 137250881Sjkim 138250881Sjkim /* sign H */ 139250881Sjkim kex->sign(server_host_private, server_host_public, &signature, &slen, 140250881Sjkim hash, hashlen); 141250881Sjkim 142250881Sjkim /* destroy_sensitive_data(); */ 143250881Sjkim 144250881Sjkim /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ 145250881Sjkim packet_start(SSH2_MSG_KEX_ECDH_REPLY); 146250881Sjkim packet_put_string(server_host_key_blob, sbloblen); 147250881Sjkim packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); 148250881Sjkim packet_put_string(signature, slen); 149250881Sjkim packet_send(); 150250881Sjkim 151250881Sjkim free(signature); 152250881Sjkim free(server_host_key_blob); 153250881Sjkim /* have keys, free server key */ 154250881Sjkim EC_KEY_free(server_key); 155250881Sjkim 156250881Sjkim kex_derive_keys(kex, hash, hashlen, shared_secret); 157250881Sjkim BN_clear_free(shared_secret); 158250881Sjkim kex_finish(kex); 159250881Sjkim} 160250881Sjkim#else /* OPENSSL_HAS_ECC */ 161250881Sjkimvoid 162250881Sjkimkexecdh_server(Kex *kex) 163250881Sjkim{ 164250881Sjkim fatal("ECC support is not enabled"); 165250881Sjkim} 166250881Sjkim#endif /* OPENSSL_HAS_ECC */ 167250881Sjkim