x25519/x448 - reject all-zero shared secrets

This commit is contained in:
Karel Miko 2026-05-03 11:00:29 +02:00 committed by Steffen Jaeckel
parent efad039f19
commit 71f45fedbc
4 changed files with 64 additions and 0 deletions

View file

@ -21,6 +21,9 @@ int x25519_shared_secret(const curve25519_key *private_key,
const curve25519_key *public_key,
unsigned char *out, unsigned long *outlen)
{
unsigned char nonzero = 0;
unsigned long x;
LTC_ARGCHK(private_key != NULL);
LTC_ARGCHK(public_key != NULL);
LTC_ARGCHK(out != NULL);
@ -37,6 +40,10 @@ int x25519_shared_secret(const curve25519_key *private_key,
tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub);
*outlen = 32uL;
/* Reject all-zero shared secrets; RFC 7748 Section 6.1 says peers MAY check for this */
for (x = 0; x < *outlen; ++x) nonzero |= out[x];
if (nonzero == 0) return CRYPT_INVALID_PACKET;
return CRYPT_OK;
}

View file

@ -21,6 +21,9 @@ int x448_shared_secret(const curve448_key *private_key,
const curve448_key *public_key,
unsigned char *out, unsigned long *outlen)
{
unsigned char nonzero = 0;
unsigned long x;
LTC_ARGCHK(private_key != NULL);
LTC_ARGCHK(public_key != NULL);
LTC_ARGCHK(out != NULL);
@ -37,6 +40,10 @@ int x448_shared_secret(const curve448_key *private_key,
ec448_scalarmult_internal(out, private_key->priv, public_key->pub);
*outlen = 56uL;
/* Reject all-zero shared secrets; RFC 7748 Section 6.2 says peers MAY check for this */
for (x = 0; x < *outlen; ++x) nonzero |= out[x];
if (nonzero == 0) return CRYPT_INVALID_PACKET;
return CRYPT_OK;
}

View file

@ -218,6 +218,30 @@ static int s_x25519_compat_test(void)
return CRYPT_OK;
}
static int s_x25519_zero_shared_secret_test(void)
{
curve25519_key alice, bob, zero_pub;
unsigned char shared[32], zeros[32];
unsigned long len;
int prng_idx = find_prng("yarrow");
zeromem(zeros, sizeof(zeros));
DO(x25519_make_key(&yarrow_prng, prng_idx, &alice));
DO(x25519_make_key(&yarrow_prng, prng_idx, &bob));
len = sizeof(shared);
DO(x25519_shared_secret(&alice, &bob, shared, &len));
ENSURE(len == sizeof(shared));
DO(x25519_import_raw(zeros, sizeof(zeros), PK_PUBLIC, &zero_pub));
len = sizeof(shared);
SHOULD_FAIL_WITH(x25519_shared_secret(&alice, &zero_pub, shared, &len), CRYPT_INVALID_PACKET);
return CRYPT_OK;
}
/**
Test the x25519 system
@return CRYPT_OK if successful
@ -226,6 +250,7 @@ int x25519_test(void)
{
DO(s_rfc_7748_5_2_test());
DO(s_rfc_7748_6_test());
DO(s_x25519_zero_shared_secret_test());
return CRYPT_OK;
}

View file

@ -227,12 +227,37 @@ static int s_x448_compat_test(void)
return CRYPT_OK;
}
static int s_x448_zero_shared_secret_test(void)
{
curve448_key alice, bob, zero_pub;
unsigned char shared[56], zeros[56];
unsigned long len;
int prng_idx = find_prng("yarrow");
zeromem(zeros, sizeof(zeros));
DO(x448_make_key(&yarrow_prng, prng_idx, &alice));
DO(x448_make_key(&yarrow_prng, prng_idx, &bob));
len = sizeof(shared);
DO(x448_shared_secret(&alice, &bob, shared, &len));
ENSURE(len == sizeof(shared));
DO(x448_import_raw(zeros, sizeof(zeros), PK_PUBLIC, &zero_pub));
len = sizeof(shared);
SHOULD_FAIL_WITH(x448_shared_secret(&alice, &zero_pub, shared, &len), CRYPT_INVALID_PACKET);
return CRYPT_OK;
}
int x448_test(void)
{
DO(s_x448_rfc7748_scalarmult_test());
DO(s_x448_rfc7748_iter_test());
DO(s_x448_keygen_dh_test());
DO(s_x448_wycheproof_special_test());
DO(s_x448_zero_shared_secret_test());
return CRYPT_OK;
}