upstream: pass values used in KEX hash computation as sshbuf

rather than pointer+len

suggested by me; implemented by markus@ ok me

OpenBSD-Commit-ID: 994f33c464f4a9e0f1d21909fa3e379f5a0910f0
This commit is contained in:
djm@openbsd.org 2019-01-21 10:35:09 +00:00 committed by Damien Miller
parent 4b83e2a2cc
commit 71e67fff94
9 changed files with 98 additions and 89 deletions

22
kex.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.103 2019/01/21 10:33:49 djm Exp $ */ /* $OpenBSD: kex.h,v 1.104 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -211,24 +211,24 @@ int kex_kem_client(struct ssh *);
int kex_kem_server(struct ssh *); int kex_kem_server(struct ssh *);
int kex_dh_keypair(struct kex *); int kex_dh_keypair(struct kex *);
int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
struct sshbuf **); struct sshbuf **);
int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
int kex_ecdh_keypair(struct kex *); int kex_ecdh_keypair(struct kex *);
int kex_ecdh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
struct sshbuf **); struct sshbuf **);
int kex_ecdh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
int kex_c25519_keypair(struct kex *); int kex_c25519_keypair(struct kex *);
int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
struct sshbuf **); struct sshbuf **);
int kex_c25519_dec(struct kex *, const u_char *, size_t, struct sshbuf **); int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
int kex_kem_sntrup4591761x25519_keypair(struct kex *); int kex_kem_sntrup4591761x25519_keypair(struct kex *);
int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *,
struct sshbuf **, struct sshbuf **); struct sshbuf **, struct sshbuf **);
int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *,
struct sshbuf **); struct sshbuf **);
int kex_dh_keygen(struct kex *); int kex_dh_keygen(struct kex *);
@ -243,8 +243,8 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *,
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const struct sshbuf *, const struct sshbuf *,
const u_char *, size_t, u_char *, size_t *); const struct sshbuf *, u_char *, size_t *);
void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexc25519.c,v 1.14 2019/01/21 10:24:09 djm Exp $ */ /* $OpenBSD: kexc25519.c,v 1.15 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved.
@ -96,9 +96,9 @@ kex_c25519_hash(
const u_char *ckexinit, size_t ckexinitlen, const u_char *ckexinit, size_t ckexinitlen,
const u_char *skexinit, size_t skexinitlen, const u_char *skexinit, size_t skexinitlen,
const u_char *serverhostkeyblob, size_t sbloblen, const u_char *serverhostkeyblob, size_t sbloblen,
const u_char *client_pub, size_t client_pub_len, const struct sshbuf *client_pub,
const u_char *server_pub, size_t server_pub_len, const struct sshbuf *server_pub,
const u_char *shared_secret, size_t secretlen, const struct sshbuf *shared_secret,
u_char *hash, size_t *hashlen) u_char *hash, size_t *hashlen)
{ {
struct sshbuf *b; struct sshbuf *b;
@ -118,9 +118,9 @@ kex_c25519_hash(
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
(r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
(r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
(r = sshbuf_put_string(b, client_pub, client_pub_len)) != 0 || (r = sshbuf_put_stringb(b, client_pub)) != 0 ||
(r = sshbuf_put_string(b, server_pub, server_pub_len)) != 0 || (r = sshbuf_put_stringb(b, server_pub)) != 0 ||
(r = sshbuf_put(b, shared_secret, secretlen)) != 0) { (r = sshbuf_putb(b, shared_secret)) != 0) {
sshbuf_free(b); sshbuf_free(b);
return r; return r;
} }
@ -162,11 +162,12 @@ kex_c25519_keypair(struct kex *kex)
} }
int int
kex_c25519_enc(struct kex *kex, const u_char *pkblob, kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
{ {
struct sshbuf *server_blob = NULL; struct sshbuf *server_blob = NULL;
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
const u_char *client_pub;
u_char *server_pub; u_char *server_pub;
u_char server_key[CURVE25519_SIZE]; u_char server_key[CURVE25519_SIZE];
int r; int r;
@ -174,12 +175,13 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob,
*server_blobp = NULL; *server_blobp = NULL;
*shared_secretp = NULL; *shared_secretp = NULL;
if (pklen != CURVE25519_SIZE) { if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
r = SSH_ERR_SIGNATURE_INVALID; r = SSH_ERR_SIGNATURE_INVALID;
goto out; goto out;
} }
client_pub = sshbuf_ptr(client_blob);
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH
dump_digest("client public key 25519:", pkblob, CURVE25519_SIZE); dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
#endif #endif
/* allocate space for encrypted KEM key and ECDH pub key */ /* allocate space for encrypted KEM key and ECDH pub key */
if ((server_blob = sshbuf_new()) == NULL) { if ((server_blob = sshbuf_new()) == NULL) {
@ -194,7 +196,7 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob,
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = kexc25519_shared_key_ext(server_key, pkblob, buf, 0)) < 0) if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
goto out; goto out;
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH
dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
@ -212,27 +214,29 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob,
} }
int int
kex_c25519_dec(struct kex *kex, const u_char *pkblob, kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
size_t pklen, struct sshbuf **shared_secretp) struct sshbuf **shared_secretp)
{ {
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
const u_char *server_pub;
int r; int r;
*shared_secretp = NULL; *shared_secretp = NULL;
if (pklen != CURVE25519_SIZE) { if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
r = SSH_ERR_SIGNATURE_INVALID; r = SSH_ERR_SIGNATURE_INVALID;
goto out; goto out;
} }
server_pub = sshbuf_ptr(server_blob);
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH
dump_digest("server public key c25519:", pkblob, CURVE25519_SIZE); dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
#endif #endif
/* shared secret */ /* shared secret */
if ((buf = sshbuf_new()) == NULL) { if ((buf = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, pkblob, if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
buf, 0)) < 0) buf, 0)) < 0)
goto out; goto out;
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH

16
kexdh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexdh.c,v 1.30 2019/01/21 10:28:01 djm Exp $ */ /* $OpenBSD: kexdh.c,v 1.31 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
* *
@ -136,7 +136,7 @@ kex_dh_keypair(struct kex *kex)
} }
int int
kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
struct sshbuf **server_blobp, struct sshbuf **shared_secretp) struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
{ {
const BIGNUM *pub_key; const BIGNUM *pub_key;
@ -156,7 +156,7 @@ kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen,
if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 || if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
(r = sshbuf_get_u32(server_blob, NULL)) != 0) (r = sshbuf_get_u32(server_blob, NULL)) != 0)
goto out; goto out;
if ((r = kex_dh_dec(kex, pkblob, pklen, shared_secretp)) != 0) if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
goto out; goto out;
*server_blobp = server_blob; *server_blobp = server_blob;
server_blob = NULL; server_blob = NULL;
@ -168,7 +168,7 @@ kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen,
} }
int int
kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
struct sshbuf **shared_secretp) struct sshbuf **shared_secretp)
{ {
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
@ -181,13 +181,9 @@ kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen,
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = sshbuf_put_u32(buf, pklen)) != 0 || if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
(r = sshbuf_put(buf, pkblob, pklen)) != 0) { (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
goto out; goto out;
}
if ((r = sshbuf_get_bignum2(buf, &dh_pub)) != 0) {
goto out;
}
sshbuf_reset(buf); sshbuf_reset(buf);
if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0) if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0)
goto out; goto out;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexecdh.c,v 1.8 2019/01/21 10:29:56 djm Exp $ */ /* $OpenBSD: kexecdh.c,v 1.9 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved.
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
@ -43,7 +43,7 @@
#include "ssherr.h" #include "ssherr.h"
static int static int
kex_ecdh_dec_key_group(struct kex *, const u_char *, size_t, EC_KEY *key, kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
const EC_GROUP *, struct sshbuf **); const EC_GROUP *, struct sshbuf **);
int int
@ -89,7 +89,7 @@ kex_ecdh_keypair(struct kex *kex)
} }
int int
kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
struct sshbuf **server_blobp, struct sshbuf **shared_secretp) struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
{ {
const EC_GROUP *group; const EC_GROUP *group;
@ -123,7 +123,7 @@ kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen,
if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 || if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
(r = sshbuf_get_u32(server_blob, NULL)) != 0) (r = sshbuf_get_u32(server_blob, NULL)) != 0)
goto out; goto out;
if ((r = kex_ecdh_dec_key_group(kex, pkblob, pklen, server_key, group, if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group,
shared_secretp)) != 0) shared_secretp)) != 0)
goto out; goto out;
*server_blobp = server_blob; *server_blobp = server_blob;
@ -135,7 +135,7 @@ kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen,
} }
static int static int
kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp) EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
{ {
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
@ -151,10 +151,8 @@ kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen,
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = sshbuf_put_u32(buf, pklen)) != 0 || if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
(r = sshbuf_put(buf, pkblob, pklen)) != 0) {
goto out; goto out;
}
if ((dh_pub = EC_POINT_new(group)) == NULL) { if ((dh_pub = EC_POINT_new(group)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
@ -199,12 +197,12 @@ kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen,
} }
int int
kex_ecdh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
struct sshbuf **shared_secretp) struct sshbuf **shared_secretp)
{ {
int r; int r;
r = kex_ecdh_dec_key_group(kex, pkblob, pklen, kex->ec_client_key, r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key,
kex->ec_group, shared_secretp); kex->ec_group, shared_secretp);
EC_KEY_free(kex->ec_client_key); EC_KEY_free(kex->ec_client_key);
kex->ec_client_key = NULL; kex->ec_client_key = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexkemc.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* $OpenBSD: kexkemc.c,v 1.5 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
* *
@ -85,10 +85,10 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
struct kex *kex = ssh->kex; struct kex *kex = ssh->kex;
struct sshkey *server_host_key = NULL; struct sshkey *server_host_key = NULL;
struct sshbuf *shared_secret = NULL; struct sshbuf *shared_secret = NULL;
u_char *server_pubkey = NULL; struct sshbuf *server_blob = NULL;
u_char *server_host_key_blob = NULL, *signature = NULL; u_char *server_host_key_blob = NULL, *signature = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH]; u_char hash[SSH_DIGEST_MAX_LENGTH];
size_t slen, pklen, sbloblen, hashlen; size_t slen, sbloblen, hashlen;
int r; int r;
/* hostkey */ /* hostkey */
@ -102,7 +102,7 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
/* Q_S, server public key */ /* Q_S, server public key */
/* signed H */ /* signed H */
if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
(r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) (r = sshpkt_get_end(ssh)) != 0)
goto out; goto out;
@ -114,16 +114,16 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
case KEX_DH_GRP14_SHA256: case KEX_DH_GRP14_SHA256:
case KEX_DH_GRP16_SHA512: case KEX_DH_GRP16_SHA512:
case KEX_DH_GRP18_SHA512: case KEX_DH_GRP18_SHA512:
r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); r = kex_dh_dec(kex, server_blob, &shared_secret);
break; break;
case KEX_ECDH_SHA2: case KEX_ECDH_SHA2:
r = kex_ecdh_dec(kex, server_pubkey, pklen, &shared_secret); r = kex_ecdh_dec(kex, server_blob, &shared_secret);
break; break;
case KEX_C25519_SHA256: case KEX_C25519_SHA256:
r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); r = kex_c25519_dec(kex, server_blob, &shared_secret);
break; break;
case KEX_KEM_SNTRUP4591761X25519_SHA512: case KEX_KEM_SNTRUP4591761X25519_SHA512:
r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, r = kex_kem_sntrup4591761x25519_dec(kex, server_blob,
&shared_secret); &shared_secret);
break; break;
default: default:
@ -142,9 +142,9 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->my), sshbuf_len(kex->my),
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
sshbuf_ptr(kex->kem_client_pub), sshbuf_len(kex->kem_client_pub), kex->kem_client_pub,
server_pubkey, pklen, server_blob,
sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
goto out; goto out;
@ -160,9 +160,9 @@ out:
explicit_bzero(kex->sntrup4591761_client_key, explicit_bzero(kex->sntrup4591761_client_key,
sizeof(kex->sntrup4591761_client_key)); sizeof(kex->sntrup4591761_client_key));
free(server_host_key_blob); free(server_host_key_blob);
free(server_pubkey);
free(signature); free(signature);
sshkey_free(server_host_key); sshkey_free(server_host_key);
sshbuf_free(server_blob);
sshbuf_free(shared_secret); sshbuf_free(shared_secret);
sshbuf_free(kex->kem_client_pub); sshbuf_free(kex->kem_client_pub);
kex->kem_client_pub = NULL; kex->kem_client_pub = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexkems.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* $OpenBSD: kexkems.c,v 1.5 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
* *
@ -53,17 +53,17 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh)
struct sshkey *server_host_private, *server_host_public; struct sshkey *server_host_private, *server_host_public;
struct sshbuf *shared_secret = NULL; struct sshbuf *shared_secret = NULL;
struct sshbuf *server_pubkey = NULL; struct sshbuf *server_pubkey = NULL;
struct sshbuf *client_pubkey = NULL;
u_char *server_host_key_blob = NULL, *signature = NULL; u_char *server_host_key_blob = NULL, *signature = NULL;
u_char *client_pubkey = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH]; u_char hash[SSH_DIGEST_MAX_LENGTH];
size_t slen, pklen, sbloblen, hashlen; size_t slen, sbloblen, hashlen;
int r; int r;
if ((r = kex_load_hostkey(ssh, &server_host_private, if ((r = kex_load_hostkey(ssh, &server_host_private,
&server_host_public)) != 0) &server_host_public)) != 0)
goto out; goto out;
if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) (r = sshpkt_get_end(ssh)) != 0)
goto out; goto out;
@ -74,19 +74,19 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh)
case KEX_DH_GRP14_SHA256: case KEX_DH_GRP14_SHA256:
case KEX_DH_GRP16_SHA512: case KEX_DH_GRP16_SHA512:
case KEX_DH_GRP18_SHA512: case KEX_DH_GRP18_SHA512:
r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
&shared_secret); &shared_secret);
break; break;
case KEX_ECDH_SHA2: case KEX_ECDH_SHA2:
r = kex_ecdh_enc(kex, client_pubkey, pklen, &server_pubkey, r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
&shared_secret); &shared_secret);
break; break;
case KEX_C25519_SHA256: case KEX_C25519_SHA256:
r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
&shared_secret); &shared_secret);
break; break;
case KEX_KEM_SNTRUP4591761X25519_SHA512: case KEX_KEM_SNTRUP4591761X25519_SHA512:
r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey,
&server_pubkey, &shared_secret); &server_pubkey, &shared_secret);
break; break;
default: default:
@ -108,9 +108,9 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh)
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->my), sshbuf_len(kex->my),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
client_pubkey, pklen, client_pubkey,
sshbuf_ptr(server_pubkey), sshbuf_len(server_pubkey), server_pubkey,
sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
goto out; goto out;
@ -133,8 +133,8 @@ out:
explicit_bzero(hash, sizeof(hash)); explicit_bzero(hash, sizeof(hash));
free(server_host_key_blob); free(server_host_key_blob);
free(signature); free(signature);
free(client_pubkey);
sshbuf_free(shared_secret); sshbuf_free(shared_secret);
sshbuf_free(client_pubkey);
sshbuf_free(server_pubkey); sshbuf_free(server_pubkey);
return r; return r;
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexsntrup4591761x25519.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ /* $OpenBSD: kexsntrup4591761x25519.c,v 1.2 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved.
* *
@ -66,11 +66,13 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
} }
int int
kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, kex_kem_sntrup4591761x25519_enc(struct kex *kex,
size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) const struct sshbuf *client_blob, struct sshbuf **server_blobp,
struct sshbuf **shared_secretp)
{ {
struct sshbuf *server_blob = NULL; struct sshbuf *server_blob = NULL;
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
const u_char *client_pub;
u_char *kem_key, *ciphertext, *server_pub; u_char *kem_key, *ciphertext, *server_pub;
u_char server_key[CURVE25519_SIZE]; u_char server_key[CURVE25519_SIZE];
u_char hash[SSH_DIGEST_MAX_LENGTH]; u_char hash[SSH_DIGEST_MAX_LENGTH];
@ -80,17 +82,19 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob,
*server_blobp = NULL; *server_blobp = NULL;
*shared_secretp = NULL; *shared_secretp = NULL;
/* pkblob contains both KEM and ECDH client pubkeys */ /* client_blob contains both KEM and ECDH client pubkeys */
need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
if (pklen != need) { if (sshbuf_len(client_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID; r = SSH_ERR_SIGNATURE_INVALID;
goto out; goto out;
} }
client_pub = sshbuf_ptr(client_blob);
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH
dump_digest("client public key sntrup4591761:", pkblob, dump_digest("client public key sntrup4591761:", client_pub,
crypto_kem_sntrup4591761_PUBLICKEYBYTES); crypto_kem_sntrup4591761_PUBLICKEYBYTES);
dump_digest("client public key 25519:", dump_digest("client public key 25519:",
pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, CURVE25519_SIZE); client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES,
CURVE25519_SIZE);
#endif #endif
/* allocate buffer for concatenation of KEM key and ECDH shared key */ /* allocate buffer for concatenation of KEM key and ECDH shared key */
/* the buffer will be hashed and the result is the shared secret */ /* the buffer will be hashed and the result is the shared secret */
@ -110,13 +114,13 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob,
if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0) if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
goto out; goto out;
/* generate and encrypt KEM key with client key */ /* generate and encrypt KEM key with client key */
crypto_kem_sntrup4591761_enc(ciphertext, kem_key, pkblob); crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub);
/* generate ECDH key pair, store server pubkey after ciphertext */ /* generate ECDH key pair, store server pubkey after ciphertext */
server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
kexc25519_keygen(server_key, server_pub); kexc25519_keygen(server_key, server_pub);
/* append ECDH shared key */ /* append ECDH shared key */
if ((r = kexc25519_shared_key_ext(server_key, client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, buf, 1)) < 0) if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
goto out; goto out;
if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
goto out; goto out;
@ -149,8 +153,8 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob,
} }
int int
kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob, kex_kem_sntrup4591761x25519_dec(struct kex *kex,
size_t pklen, struct sshbuf **shared_secretp) const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
{ {
struct sshbuf *buf = NULL; struct sshbuf *buf = NULL;
u_char *kem_key = NULL; u_char *kem_key = NULL;
@ -162,12 +166,12 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob,
*shared_secretp = NULL; *shared_secretp = NULL;
need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
if (pklen != need) { if (sshbuf_len(server_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID; r = SSH_ERR_SIGNATURE_INVALID;
goto out; goto out;
} }
ciphertext = pkblob; ciphertext = sshbuf_ptr(server_blob);
server_pub = pkblob + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
#ifdef DEBUG_KEXECDH #ifdef DEBUG_KEXECDH
dump_digest("server cipher text:", ciphertext, dump_digest("server cipher text:", ciphertext,
crypto_kem_sntrup4591761_CIPHERTEXTBYTES); crypto_kem_sntrup4591761_CIPHERTEXTBYTES);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.281 2019/01/21 09:54:11 djm Exp $ */ /* $OpenBSD: packet.c,v 1.282 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -2483,6 +2483,12 @@ sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
return sshbuf_put_stringb(ssh->state->outgoing_packet, v); return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
} }
int
sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp)
{
return sshbuf_froms(ssh->state->incoming_packet, valp);
}
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
#ifdef OPENSSL_HAS_ECC #ifdef OPENSSL_HAS_ECC
int int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.89 2019/01/21 09:54:11 djm Exp $ */ /* $OpenBSD: packet.h,v 1.90 2019/01/21 10:35:09 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -199,6 +199,7 @@ int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp);
int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp);
int sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp);
int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g);
int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp); int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp);
int sshpkt_get_end(struct ssh *ssh); int sshpkt_get_end(struct ssh *ssh);