Skip to content

Commit

Permalink
Update/replace the experimental post-quantim hybrid key exchange
Browse files Browse the repository at this point in the history
method based on Streamlined NTRU Prime (coupled with X25519).

The previous sntrup4591761x25519-sha512@tinyssh.org method is
replaced with sntrup761x25519-sha512@openssh.com. Per the authors,
sntrup4591761 was replaced almost two years ago by sntrup761.

The sntrup761 implementaion, like sntrup4591761 before it, is public
domain code extracted from the SUPERCOP cryptography benchmark
suite (https://bench.cr.yp.to/supercop.html).

Thanks for Daniel J Bernstein for guidance on algorithm selection.
Patch from Tobias Heider; feedback & ok markus@ and myself

(note this both the updated method and the one that it replaced are
disabled by default)
  • Loading branch information
djmdjm committed Dec 29, 2020
1 parent b6faad1 commit 3e284e1
Show file tree
Hide file tree
Showing 16 changed files with 1,496 additions and 1,207 deletions.
6 changes: 3 additions & 3 deletions usr.bin/ssh/Makefile.inc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# $OpenBSD: Makefile.inc,v 1.85 2020/10/16 13:24:45 djm Exp $
# $OpenBSD: Makefile.inc,v 1.86 2020/12/29 00:59:15 djm Exp $

.include <bsd.own.mk>

Expand Down Expand Up @@ -69,8 +69,8 @@ SRCS_KEXS+= kexgexs.c
SRCS_KEX+= kexc25519.c
SRCS_KEX+= smult_curve25519_ref.c
SRCS_KEX+= kexgen.c
SRCS_KEX+= kexsntrup4591761x25519.c
SRCS_KEX+= sntrup4591761.c
SRCS_KEX+= kexsntrup761x25519.c
SRCS_KEX+= sntrup761.c

SRCS_KEY+= sshkey.c
SRCS_KEY+= cipher.c
Expand Down
16 changes: 8 additions & 8 deletions usr.bin/ssh/crypto_api.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */
/* $OpenBSD: crypto_api.h,v 1.6 2020/12/29 00:59:15 djm Exp $ */

/*
* Assembled from generated headers and source files by Markus Friedl.
Expand Down Expand Up @@ -38,15 +38,15 @@ int crypto_sign_ed25519_open(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *);

#define crypto_kem_sntrup4591761_PUBLICKEYBYTES 1218
#define crypto_kem_sntrup4591761_SECRETKEYBYTES 1600
#define crypto_kem_sntrup4591761_CIPHERTEXTBYTES 1047
#define crypto_kem_sntrup4591761_BYTES 32
#define crypto_kem_sntrup761_PUBLICKEYBYTES 1158
#define crypto_kem_sntrup761_SECRETKEYBYTES 1763
#define crypto_kem_sntrup761_CIPHERTEXTBYTES 1039
#define crypto_kem_sntrup761_BYTES 32

int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k,
int crypto_kem_sntrup761_enc(unsigned char *cstr, unsigned char *k,
const unsigned char *pk);
int crypto_kem_sntrup4591761_dec(unsigned char *k,
int crypto_kem_sntrup761_dec(unsigned char *k,
const unsigned char *cstr, const unsigned char *sk);
int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk);
int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk);

#endif /* crypto_api_h */
4 changes: 2 additions & 2 deletions usr.bin/ssh/kex.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.162 2020/12/04 02:27:57 djm Exp $ */
/* $OpenBSD: kex.c,v 1.163 2020/12/29 00:59:15 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
Expand Down Expand Up @@ -98,7 +98,7 @@ static const struct kexalg kexalgs[] = {
#endif
{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
{ KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0,
{ KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0,
SSH_DIGEST_SHA512 },
{ NULL, 0, -1, -1},
};
Expand Down
14 changes: 7 additions & 7 deletions usr.bin/ssh/kex.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.111 2020/10/07 02:22:23 djm Exp $ */
/* $OpenBSD: kex.h,v 1.112 2020/12/29 00:59:15 djm Exp $ */

/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
Expand Down Expand Up @@ -55,7 +55,7 @@
#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
#define KEX_CURVE25519_SHA256 "curve25519-sha256"
#define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org"
#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org"
#define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com"

#define COMP_NONE 0
/* pre-auth compression (COMP_ZLIB) is only supported in the client */
Expand Down Expand Up @@ -94,7 +94,7 @@ enum kex_exchange {
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_C25519_SHA256,
KEX_KEM_SNTRUP4591761X25519_SHA512,
KEX_KEM_SNTRUP761X25519_SHA512,
KEX_MAX
};

Expand Down Expand Up @@ -161,7 +161,7 @@ struct kex {
const EC_GROUP *ec_group; /* ECDH */
u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */
u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */
u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */
struct sshbuf *client_pub;
};

Expand Down Expand Up @@ -211,10 +211,10 @@ int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
struct sshbuf **);
int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **);

int kex_kem_sntrup4591761x25519_keypair(struct kex *);
int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *,
int kex_kem_sntrup761x25519_keypair(struct kex *);
int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *,
struct sshbuf **, struct sshbuf **);
int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *,
int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *,
struct sshbuf **);

int kex_dh_keygen(struct kex *);
Expand Down
18 changes: 9 additions & 9 deletions usr.bin/ssh/kexgen.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: kexgen.c,v 1.4 2019/11/25 00:51:37 djm Exp $ */
/* $OpenBSD: kexgen.c,v 1.5 2020/12/29 00:59:15 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
Expand Down Expand Up @@ -114,8 +114,8 @@ kex_gen_client(struct ssh *ssh)
case KEX_C25519_SHA256:
r = kex_c25519_keypair(kex);
break;
case KEX_KEM_SNTRUP4591761X25519_SHA512:
r = kex_kem_sntrup4591761x25519_keypair(kex);
case KEX_KEM_SNTRUP761X25519_SHA512:
r = kex_kem_sntrup761x25519_keypair(kex);
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
Expand Down Expand Up @@ -182,8 +182,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
case KEX_C25519_SHA256:
r = kex_c25519_dec(kex, server_blob, &shared_secret);
break;
case KEX_KEM_SNTRUP4591761X25519_SHA512:
r = kex_kem_sntrup4591761x25519_dec(kex, server_blob,
case KEX_KEM_SNTRUP761X25519_SHA512:
r = kex_kem_sntrup761x25519_dec(kex, server_blob,
&shared_secret);
break;
default:
Expand Down Expand Up @@ -217,8 +217,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
out:
explicit_bzero(hash, sizeof(hash));
explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
explicit_bzero(kex->sntrup4591761_client_key,
sizeof(kex->sntrup4591761_client_key));
explicit_bzero(kex->sntrup761_client_key,
sizeof(kex->sntrup761_client_key));
sshbuf_free(server_host_key_blob);
free(signature);
sshbuf_free(tmp);
Expand Down Expand Up @@ -279,8 +279,8 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
&shared_secret);
break;
case KEX_KEM_SNTRUP4591761X25519_SHA512:
r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey,
case KEX_KEM_SNTRUP761X25519_SHA512:
r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
&server_pubkey, &shared_secret);
break;
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: kexsntrup4591761x25519.c,v 1.4 2020/12/19 22:09:21 tobhe Exp $ */
/* $OpenBSD: kexsntrup761x25519.c,v 1.1 2020/12/29 00:59:15 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
Expand Down Expand Up @@ -36,7 +36,7 @@
#include "ssherr.h"

int
kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
kex_kem_sntrup761x25519_keypair(struct kex *kex)
{
struct sshbuf *buf = NULL;
u_char *cp = NULL;
Expand All @@ -45,15 +45,15 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex)

if ((buf = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
goto out;
crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key);
crypto_kem_sntrup761_keypair(cp, kex->sntrup761_client_key);
#ifdef DEBUG_KEXECDH
dump_digest("client public key sntrup4591761:", cp,
crypto_kem_sntrup4591761_PUBLICKEYBYTES);
dump_digest("client public key sntrup761:", cp,
crypto_kem_sntrup761_PUBLICKEYBYTES);
#endif
cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
cp += crypto_kem_sntrup761_PUBLICKEYBYTES;
kexc25519_keygen(kex->c25519_client_key, cp);
#ifdef DEBUG_KEXECDH
dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
Expand All @@ -66,7 +66,7 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
}

int
kex_kem_sntrup4591761x25519_enc(struct kex *kex,
kex_kem_sntrup761x25519_enc(struct kex *kex,
const struct sshbuf *client_blob, struct sshbuf **server_blobp,
struct sshbuf **shared_secretp)
{
Expand All @@ -83,17 +83,17 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
*shared_secretp = NULL;

/* client_blob contains both KEM and ECDH client pubkeys */
need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
if (sshbuf_len(client_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID;
goto out;
}
client_pub = sshbuf_ptr(client_blob);
#ifdef DEBUG_KEXECDH
dump_digest("client public key sntrup4591761:", client_pub,
crypto_kem_sntrup4591761_PUBLICKEYBYTES);
dump_digest("client public key sntrup761:", client_pub,
crypto_kem_sntrup761_PUBLICKEYBYTES);
dump_digest("client public key 25519:",
client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES,
client_pub + crypto_kem_sntrup761_PUBLICKEYBYTES,
CURVE25519_SIZE);
#endif
/* allocate buffer for concatenation of KEM key and ECDH shared key */
Expand All @@ -102,32 +102,32 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
&kem_key)) != 0)
goto out;
/* allocate space for encrypted KEM key and ECDH pub key */
if ((server_blob = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
goto out;
/* generate and encrypt KEM key with client key */
crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub);
crypto_kem_sntrup761_enc(ciphertext, kem_key, client_pub);
/* generate ECDH key pair, store server pubkey after ciphertext */
server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
kexc25519_keygen(server_key, server_pub);
/* append ECDH shared key */
client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
client_pub += crypto_kem_sntrup761_PUBLICKEYBYTES;
if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
goto out;
if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
goto out;
#ifdef DEBUG_KEXECDH
dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
dump_digest("server cipher text:", ciphertext,
crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
crypto_kem_sntrup761_CIPHERTEXTBYTES);
dump_digest("server kem key:", kem_key, sizeof(kem_key));
dump_digest("concatenation of KEM key and ECDH shared key:",
sshbuf_ptr(buf), sshbuf_len(buf));
Expand All @@ -153,7 +153,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
}

int
kex_kem_sntrup4591761x25519_dec(struct kex *kex,
kex_kem_sntrup761x25519_dec(struct kex *kex,
const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
{
struct sshbuf *buf = NULL;
Expand All @@ -165,35 +165,35 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex,

*shared_secretp = NULL;

need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
if (sshbuf_len(server_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID;
goto out;
}
ciphertext = sshbuf_ptr(server_blob);
server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
#ifdef DEBUG_KEXECDH
dump_digest("server cipher text:", ciphertext,
crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
crypto_kem_sntrup761_CIPHERTEXTBYTES);
dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
#endif
/* hash concatenation of KEM key and ECDH shared key */
if ((buf = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
&kem_key)) != 0)
goto out;
decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext,
kex->sntrup4591761_client_key);
decoded = crypto_kem_sntrup761_dec(kem_key, ciphertext,
kex->sntrup761_client_key);
if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
buf, 1)) < 0)
goto out;
if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
goto out;
#ifdef DEBUG_KEXECDH
dump_digest("client kem key:", kem_key, crypto_kem_sntrup4591761_BYTES);
dump_digest("client kem key:", kem_key, crypto_kem_sntrup761_BYTES);
dump_digest("concatenation of KEM key and ECDH shared key:",
sshbuf_ptr(buf), sshbuf_len(buf));
#endif
Expand Down
4 changes: 2 additions & 2 deletions usr.bin/ssh/monitor.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.218 2020/11/27 00:37:10 djm Exp $ */
/* $OpenBSD: monitor.c,v 1.219 2020/12/29 00:59:15 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
Expand Down Expand Up @@ -1429,7 +1429,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
#endif
kex->kex[KEX_C25519_SHA256] = kex_gen_server;
kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
Expand Down
Loading

0 comments on commit 3e284e1

Please sign in to comment.