Annotation of src/usr.bin/ssh/kexc25519.c, Revision 1.1
1.1 ! markus 1: /*
! 2: * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
! 3: * Copyright (c) 2010 Damien Miller. All rights reserved.
! 4: * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include <sys/types.h>
! 28:
! 29: #include <signal.h>
! 30: #include <string.h>
! 31:
! 32: #include <openssl/bn.h>
! 33: #include <openssl/evp.h>
! 34:
! 35: #include "buffer.h"
! 36: #include "ssh2.h"
! 37: #include "key.h"
! 38: #include "cipher.h"
! 39: #include "kex.h"
! 40: #include "log.h"
! 41:
! 42: extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
! 43: const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
! 44: __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
! 45: __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)))
! 46: __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE)));
! 47:
! 48: void
! 49: kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
! 50: {
! 51: static const u_char basepoint[CURVE25519_SIZE] = {9};
! 52:
! 53: arc4random_buf(key, CURVE25519_SIZE);
! 54: crypto_scalarmult_curve25519(pub, key, basepoint);
! 55: }
! 56:
! 57: BIGNUM *
! 58: kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
! 59: const u_char pub[CURVE25519_SIZE])
! 60: {
! 61: u_char shared_key[CURVE25519_SIZE];
! 62: BIGNUM *shared_secret;
! 63:
! 64: crypto_scalarmult_curve25519(shared_key, key, pub);
! 65: #ifdef DEBUG_KEXECDH
! 66: dump_digest("shared secret", shared_key, CURVE25519_SIZE);
! 67: #endif
! 68: if ((shared_secret = BN_new()) == NULL)
! 69: fatal("%s: BN_new failed", __func__);
! 70: if (BN_bin2bn(shared_key, sizeof(shared_key), shared_secret) == NULL)
! 71: fatal("%s: BN_bin2bn failed", __func__);
! 72: memset(shared_key, 0, CURVE25519_SIZE); /* XXX explicit_bzero() */
! 73: return (shared_secret);
! 74: }
! 75:
! 76: void
! 77: kex_c25519_hash(
! 78: const EVP_MD *evp_md,
! 79: char *client_version_string,
! 80: char *server_version_string,
! 81: char *ckexinit, int ckexinitlen,
! 82: char *skexinit, int skexinitlen,
! 83: u_char *serverhostkeyblob, int sbloblen,
! 84: const u_char client_dh_pub[CURVE25519_SIZE],
! 85: const u_char server_dh_pub[CURVE25519_SIZE],
! 86: const BIGNUM *shared_secret,
! 87: u_char **hash, u_int *hashlen)
! 88: {
! 89: Buffer b;
! 90: EVP_MD_CTX md;
! 91: static u_char digest[EVP_MAX_MD_SIZE];
! 92:
! 93: buffer_init(&b);
! 94: buffer_put_cstring(&b, client_version_string);
! 95: buffer_put_cstring(&b, server_version_string);
! 96:
! 97: /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
! 98: buffer_put_int(&b, ckexinitlen+1);
! 99: buffer_put_char(&b, SSH2_MSG_KEXINIT);
! 100: buffer_append(&b, ckexinit, ckexinitlen);
! 101: buffer_put_int(&b, skexinitlen+1);
! 102: buffer_put_char(&b, SSH2_MSG_KEXINIT);
! 103: buffer_append(&b, skexinit, skexinitlen);
! 104:
! 105: buffer_put_string(&b, serverhostkeyblob, sbloblen);
! 106: buffer_put_string(&b, client_dh_pub, CURVE25519_SIZE);
! 107: buffer_put_string(&b, server_dh_pub, CURVE25519_SIZE);
! 108: buffer_put_bignum2(&b, shared_secret);
! 109:
! 110: #ifdef DEBUG_KEX
! 111: buffer_dump(&b);
! 112: #endif
! 113: EVP_DigestInit(&md, evp_md);
! 114: EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
! 115: EVP_DigestFinal(&md, digest, NULL);
! 116:
! 117: buffer_free(&b);
! 118:
! 119: #ifdef DEBUG_KEX
! 120: dump_digest("hash", digest, EVP_MD_size(evp_md));
! 121: #endif
! 122: *hash = digest;
! 123: *hashlen = EVP_MD_size(evp_md);
! 124: }