mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 00:00:49 +02:00
25a1a20444
Add defense-in-depth checks to wc_ed{25519,448}_check_key() and
ed{25519,448}_verify_msg_final_with_sha() that reject the identity
point and other small-order public keys. Honest EdDSA key generation
never produces such keys, but wolfSSL previously accepted them on
import and verification. The guard runs at both entry points so it
holds even when a key is imported with trusted=1. New tests are gated
on !HAVE_FIPS || FIPS_VERSION3_GE(7,0,0).
873 lines
31 KiB
C
873 lines
31 KiB
C
/* test_ed448.c
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <tests/unit.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/ed448.h>
|
|
#include <wolfssl/wolfcrypt/types.h>
|
|
#include <tests/api/api.h>
|
|
#include <tests/api/test_ed448.h>
|
|
|
|
|
|
/*
|
|
* Testing wc_ed448_make_key().
|
|
*/
|
|
int test_wc_ed448_make_key(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
unsigned char pubkey[ED448_PUB_KEY_SIZE];
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_make_public(&key, pubkey, sizeof(pubkey)),
|
|
WC_NO_ERR_TRACE(ECC_PRIV_KEY_E));
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_make_key(NULL, ED448_KEY_SIZE, &key),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE - 1, &key),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE + 1, &key),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_make_key */
|
|
|
|
|
|
/*
|
|
* Testing wc_ed448_init()
|
|
*/
|
|
int test_wc_ed448_init(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448)
|
|
ed448_key key;
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_init(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_init */
|
|
|
|
/*
|
|
* Test wc_ed448_sign_msg() and wc_ed448_verify_msg()
|
|
*/
|
|
int test_wc_ed448_sign_msg(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
byte msg[] = "Everybody gets Friday off.\n";
|
|
byte sig[ED448_SIG_SIZE];
|
|
word32 msglen = sizeof(msg);
|
|
word32 siglen = sizeof(sig);
|
|
word32 badSigLen = sizeof(sig) - 1;
|
|
#ifdef HAVE_ED448_VERIFY
|
|
int verify_ok = 0; /*1 = Verify success.*/
|
|
#endif
|
|
|
|
/* Initialize stack variables. */
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
XMEMSET(sig, 0, siglen);
|
|
|
|
/* Initialize key. */
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, msglen, sig, &siglen, &key, NULL, 0), 0);
|
|
ExpectIntEQ(siglen, ED448_SIG_SIZE);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_sign_msg(NULL, msglen, sig, &siglen, &key, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, msglen, NULL, &siglen, &key, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, msglen, sig, NULL, &key, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, msglen, sig, &siglen, NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, msglen, sig, &badSigLen, &key, NULL, 0),
|
|
WC_NO_ERR_TRACE(BUFFER_E));
|
|
ExpectIntEQ(badSigLen, ED448_SIG_SIZE);
|
|
badSigLen--;
|
|
|
|
#ifdef HAVE_ED448_VERIFY
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen, msg, msglen, &verify_ok, &key,
|
|
NULL, 0), 0);
|
|
ExpectIntEQ(verify_ok, 1);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen - 1, msg, msglen, &verify_ok,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen + 1, msg, msglen, &verify_ok,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(NULL, siglen, msg, msglen, &verify_ok,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen, NULL, msglen, &verify_ok,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen, msg, msglen, NULL,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, siglen, msg, msglen, &verify_ok,
|
|
NULL, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_verify_msg(sig, badSigLen, msg, msglen, &verify_ok,
|
|
&key, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif /* Verify. */
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_sign_msg */
|
|
|
|
/*
|
|
* Test that wc_ed448_sign_msg() rejects a public-key-only key object.
|
|
* A key with pubKeySet=1 but privKeySet=0 must not silently sign.
|
|
*/
|
|
int test_wc_ed448_sign_msg_pubonly_fails(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN) && \
|
|
defined(HAVE_ED448_KEY_IMPORT) && defined(HAVE_ED448_KEY_EXPORT)
|
|
ed448_key fullKey;
|
|
ed448_key pubOnlyKey;
|
|
WC_RNG rng;
|
|
byte pubBuf[ED448_PUB_KEY_SIZE];
|
|
word32 pubSz = sizeof(pubBuf);
|
|
byte msg[] = "test message for pubonly check";
|
|
byte sig[ED448_SIG_SIZE];
|
|
word32 sigLen = sizeof(sig);
|
|
|
|
XMEMSET(&fullKey, 0, sizeof(fullKey));
|
|
XMEMSET(&pubOnlyKey, 0, sizeof(pubOnlyKey));
|
|
XMEMSET(&rng, 0, sizeof(rng));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&fullKey), 0);
|
|
ExpectIntEQ(wc_ed448_init(&pubOnlyKey), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
|
|
/* Generate a real key pair and export its public key. */
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &fullKey), 0);
|
|
ExpectIntEQ(wc_ed448_export_public(&fullKey, pubBuf, &pubSz), 0);
|
|
|
|
/* Import only the public key into a fresh key object. */
|
|
ExpectIntEQ(wc_ed448_import_public(pubBuf, pubSz, &pubOnlyKey), 0);
|
|
|
|
/* Signing with a public-key-only object must fail. */
|
|
ExpectIntEQ(wc_ed448_sign_msg(msg, sizeof(msg), sig, &sigLen,
|
|
&pubOnlyKey, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&pubOnlyKey);
|
|
wc_ed448_free(&fullKey);
|
|
#endif
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_sign_msg_pubonly_fails */
|
|
|
|
/*
|
|
* Testing wc_ed448_import_public()
|
|
*/
|
|
int test_wc_ed448_import_public(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
|
|
ed448_key pubKey;
|
|
WC_RNG rng;
|
|
const byte in[] =
|
|
"Ed448PublicKeyUnitTest.................................\n";
|
|
word32 inlen = sizeof(in);
|
|
|
|
XMEMSET(&pubKey, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&pubKey), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &pubKey), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_import_public_ex(in, inlen, &pubKey, 1), 0);
|
|
ExpectIntEQ(XMEMCMP(in, pubKey.p, inlen), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_import_public(NULL, inlen, &pubKey),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_public(in, inlen, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_public(in, inlen - 1, &pubKey),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&pubKey);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END wc_ed448_import_public */
|
|
|
|
/*
|
|
* Testing wc_ed448_import_private_key()
|
|
*/
|
|
int test_wc_ed448_import_private_key(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
const byte privKey[] =
|
|
"Ed448PrivateKeyUnitTest................................\n";
|
|
const byte pubKey[] =
|
|
"Ed448PublicKeyUnitTest.................................\n";
|
|
word32 privKeySz = sizeof(privKey);
|
|
word32 pubKeySz = sizeof(pubKey);
|
|
#ifdef HAVE_ED448_KEY_EXPORT
|
|
byte bothKeys[sizeof(privKey) + sizeof(pubKey)];
|
|
word32 bothKeysSz = sizeof(bothKeys);
|
|
#endif
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_import_private_key_ex(privKey, privKeySz, pubKey,
|
|
pubKeySz, &key, 1), 0);
|
|
ExpectIntEQ(XMEMCMP(pubKey, key.p, privKeySz), 0);
|
|
ExpectIntEQ(XMEMCMP(privKey, key.k, pubKeySz), 0);
|
|
|
|
#ifdef HAVE_ED448_KEY_EXPORT
|
|
PRIVATE_KEY_UNLOCK();
|
|
ExpectIntEQ(wc_ed448_export_private(&key, bothKeys, &bothKeysSz), 0);
|
|
PRIVATE_KEY_LOCK();
|
|
ExpectIntEQ(wc_ed448_import_private_key_ex(bothKeys, bothKeysSz, NULL, 0,
|
|
&key, 1), 0);
|
|
ExpectIntEQ(XMEMCMP(pubKey, key.p, privKeySz), 0);
|
|
ExpectIntEQ(XMEMCMP(privKey, key.k, pubKeySz), 0);
|
|
#endif
|
|
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_import_private_key(NULL, privKeySz, pubKey, pubKeySz,
|
|
&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_private_key(privKey, privKeySz, NULL, pubKeySz,
|
|
&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_private_key(privKey, privKeySz, pubKey,
|
|
pubKeySz, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_private_key(privKey, privKeySz - 1, pubKey,
|
|
pubKeySz, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_private_key(privKey, privKeySz, pubKey,
|
|
pubKeySz - 1, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_import_private_key(privKey, privKeySz, NULL, 0, &key),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_import_private_key */
|
|
|
|
/*
|
|
* Testing wc_ed448_export_public() and wc_ed448_export_private_only()
|
|
*/
|
|
int test_wc_ed448_export(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
byte priv[ED448_PRV_KEY_SIZE];
|
|
byte pub[ED448_PUB_KEY_SIZE];
|
|
word32 privSz = sizeof(priv);
|
|
word32 pubSz = sizeof(pub);
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
|
|
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
|
/* Reject export when private key not set. */
|
|
PRIVATE_KEY_UNLOCK();
|
|
ExpectIntEQ(wc_ed448_export_private_only(&key, priv, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private(&key, priv, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
PRIVATE_KEY_LOCK();
|
|
#endif /* !HAVE_FIPS || FIPS_VERSION3_GE(7,0,0) */
|
|
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_export_public(&key, pub, &pubSz), 0);
|
|
ExpectIntEQ(pubSz, ED448_KEY_SIZE);
|
|
ExpectIntEQ(XMEMCMP(key.p, pub, pubSz), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_export_public(NULL, pub, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_public(&key, NULL, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_public(&key, pub, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
PRIVATE_KEY_UNLOCK();
|
|
ExpectIntEQ(wc_ed448_export_private_only(&key, priv, &privSz), 0);
|
|
ExpectIntEQ(privSz, ED448_KEY_SIZE);
|
|
ExpectIntEQ(XMEMCMP(key.k, priv, privSz), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_export_private_only(NULL, priv, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private_only(&key, NULL, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private_only(&key, priv, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
PRIVATE_KEY_LOCK();
|
|
|
|
#ifdef HAVE_ED448_KEY_IMPORT
|
|
/* Public-only key: re-init and import just the public part; private
|
|
* exports must still fail with privKeySet == 0. */
|
|
wc_ed448_free(&key);
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_ed448_import_public(pub, pubSz, &key), 0);
|
|
|
|
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
|
PRIVATE_KEY_UNLOCK();
|
|
ExpectIntEQ(wc_ed448_export_private_only(&key, priv, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private(&key, priv, &privSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
PRIVATE_KEY_LOCK();
|
|
#endif /* !HAVE_FIPS || FIPS_VERSION3_GE(7,0,0) */
|
|
|
|
#endif
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_export */
|
|
|
|
/*
|
|
* Testing wc_ed448_size()
|
|
*/
|
|
int test_wc_ed448_size(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
ExpectIntEQ(wc_ed448_size(&key), ED448_KEY_SIZE);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_size(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wc_ed448_sig_size(&key), ED448_SIG_SIZE);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_sig_size(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wc_ed448_pub_size(&key), ED448_PUB_KEY_SIZE);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_pub_size(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wc_ed448_priv_size(&key), ED448_PRV_KEY_SIZE);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_priv_size(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_size */
|
|
|
|
/*
|
|
* Testing wc_ed448_export_private() and wc_ed448_export_key()
|
|
*/
|
|
int test_wc_ed448_exportKey(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT)
|
|
ed448_key key;
|
|
WC_RNG rng;
|
|
byte priv[ED448_PRV_KEY_SIZE];
|
|
byte pub[ED448_PUB_KEY_SIZE];
|
|
byte privOnly[ED448_PRV_KEY_SIZE];
|
|
word32 privSz = sizeof(priv);
|
|
word32 pubSz = sizeof(pub);
|
|
word32 privOnlySz = sizeof(privOnly);
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
PRIVATE_KEY_UNLOCK();
|
|
ExpectIntEQ(wc_ed448_export_private(&key, privOnly, &privOnlySz), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_export_private(NULL, privOnly, &privOnlySz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private(&key, NULL, &privOnlySz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_private(&key, privOnly, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wc_ed448_export_key(&key, priv, &privSz, pub, &pubSz), 0);
|
|
/* Test bad args. */
|
|
ExpectIntEQ(wc_ed448_export_key(NULL, priv, &privSz, pub, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_key(&key, NULL, &privSz, pub, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_key(&key, priv, NULL, pub, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_key(&key, priv, &privSz, NULL, &pubSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_ed448_export_key(&key, priv, &privSz, pub, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
PRIVATE_KEY_LOCK();
|
|
|
|
/* Cross check output. */
|
|
ExpectIntEQ(XMEMCMP(priv, privOnly, privSz), 0);
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END test_wc_ed448_exportKey */
|
|
|
|
/*
|
|
* Testing wc_Ed448PublicKeyToDer
|
|
*/
|
|
int test_wc_Ed448PublicKeyToDer(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
|
|
(defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
|
ed448_key key;
|
|
byte derBuf[1024];
|
|
|
|
XMEMSET(&key, 0, sizeof(ed448_key));
|
|
|
|
/* Test bad args */
|
|
ExpectIntEQ(wc_Ed448PublicKeyToDer(NULL, NULL, 0, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_Ed448PublicKeyToDer(&key, derBuf, 0, 0),
|
|
WC_NO_ERR_TRACE(BUFFER_E));
|
|
wc_ed448_free(&key);
|
|
|
|
/* Test good args */
|
|
if (EXPECT_SUCCESS()) {
|
|
WC_RNG rng;
|
|
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
/* length only */
|
|
ExpectIntGT(wc_Ed448PublicKeyToDer(&key, NULL, 0, 0), 0);
|
|
ExpectIntGT(wc_Ed448PublicKeyToDer(&key, NULL, 0, 1), 0);
|
|
ExpectIntGT(wc_Ed448PublicKeyToDer(&key, derBuf,
|
|
(word32)sizeof(derBuf), 1), 0);
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&key);
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* END testing wc_Ed448PublicKeyToDer */
|
|
|
|
/*
|
|
* Testing wc_Ed448KeyToDer
|
|
*/
|
|
int test_wc_Ed448KeyToDer(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
|
|
(defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
|
byte output[ONEK_BUF];
|
|
ed448_key ed448Key;
|
|
WC_RNG rng;
|
|
word32 inLen;
|
|
|
|
XMEMSET(&ed448Key, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&ed448Key), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key), 0);
|
|
inLen = (word32)sizeof(output);
|
|
|
|
/* Bad Cases */
|
|
ExpectIntEQ(wc_Ed448KeyToDer(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_Ed448KeyToDer(NULL, output, inLen),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_Ed448KeyToDer(&ed448Key, output, 0),
|
|
WC_NO_ERR_TRACE(BUFFER_E));
|
|
/* Good Cases */
|
|
/* length only */
|
|
ExpectIntGT(wc_Ed448KeyToDer(&ed448Key, NULL, 0), 0);
|
|
ExpectIntGT(wc_Ed448KeyToDer(&ed448Key, output, inLen), 0);
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&ed448Key);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* End test_wc_Ed448KeyToDer */
|
|
|
|
/*
|
|
* Testing wc_Ed448PrivateKeyToDer
|
|
*/
|
|
int test_wc_Ed448PrivateKeyToDer(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
|
|
(defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
|
byte output[ONEK_BUF];
|
|
ed448_key ed448PrivKey;
|
|
WC_RNG rng;
|
|
word32 inLen;
|
|
|
|
XMEMSET(&ed448PrivKey, 0, sizeof(ed448_key));
|
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
|
|
|
ExpectIntEQ(wc_ed448_init(&ed448PrivKey), 0);
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448PrivKey),
|
|
0);
|
|
inLen = (word32)sizeof(output);
|
|
|
|
/* Bad Cases */
|
|
ExpectIntEQ(wc_Ed448PrivateKeyToDer(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_Ed448PrivateKeyToDer(NULL, output, inLen),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wc_Ed448PrivateKeyToDer(&ed448PrivKey, output, 0),
|
|
WC_NO_ERR_TRACE(BUFFER_E));
|
|
/* Good cases */
|
|
/* length only */
|
|
ExpectIntGT(wc_Ed448PrivateKeyToDer(&ed448PrivKey, NULL, 0), 0);
|
|
ExpectIntGT(wc_Ed448PrivateKeyToDer(&ed448PrivKey, output, inLen), 0);
|
|
|
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
|
wc_ed448_free(&ed448PrivKey);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
} /* End test_wc_Ed448PrivateKeyToDer */
|
|
|
|
/*
|
|
* RFC 5958: version=v2 (1) when pub key is bundled, v1 (0) for private only. */
|
|
int test_wc_Ed448KeyToDer_oneasymkey_version(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \
|
|
defined(HAVE_ED448_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN)
|
|
ed448_key key;
|
|
ed448_key key2;
|
|
WC_RNG rng;
|
|
byte ref[512]; /* reference DER (bundled, then private only) */
|
|
byte rt[512]; /* re-export target for memcmp */
|
|
int refSz = 0;
|
|
int rtSz = 0;
|
|
word32 idx;
|
|
|
|
XMEMSET(&key, 0, sizeof(key));
|
|
XMEMSET(&key2, 0, sizeof(key2));
|
|
XMEMSET(&rng, 0, sizeof(rng));
|
|
|
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_ed448_init(&key2), 0);
|
|
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0);
|
|
|
|
/* Bundled (v=1) */
|
|
ExpectIntGT(refSz = wc_Ed448KeyToDer(&key, ref, (word32)sizeof(ref)), 0);
|
|
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 1);
|
|
idx = 0;
|
|
ExpectIntEQ(wc_Ed448PrivateKeyDecode(ref, &idx, &key2, (word32)refSz), 0);
|
|
ExpectIntEQ(rtSz = wc_Ed448KeyToDer(&key2, rt, (word32)sizeof(rt)), refSz);
|
|
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
|
|
|
|
/* Private only (v=0) */
|
|
ExpectIntGT(refSz = wc_Ed448PrivateKeyToDer(&key, ref,
|
|
(word32)sizeof(ref)), 0);
|
|
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
|
|
|
|
wc_ed448_free(&key);
|
|
wc_ed448_free(&key2);
|
|
wc_FreeRng(&rng);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Ed448 identity and small-order public keys must be rejected.
|
|
* Edwards448 has cofactor 4, so the small-order subgroup contains the
|
|
* identity, an order-2 point, and two order-4 points. With any of these
|
|
* as the public key, h*A is the neutral element and forged signatures
|
|
* verify for arbitrary messages. Gated on FIPS_VERSION3_GE(7,0,0)
|
|
* because older FIPS-certified modules do not have this check in their
|
|
* frozen copy of ed448.c. */
|
|
int test_wc_ed448_reject_small_order_keys(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) && \
|
|
defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
|
|
/* Two regressions are guarded here. Both sign-bit variants of each
|
|
* y are listed so weakening the "clear all of byte 56" mask in
|
|
* ed448_is_small_order() would be caught. The non-canonical rows
|
|
* (y = p, y = p + 1) guard against dropping the canonical-form
|
|
* coverage: fe448_from_bytes reads bytes 0-55 modulo p with no
|
|
* canonical-form check, so y = p decodes to 0 and y = p + 1
|
|
* decodes to 1, both of which are small order. */
|
|
static const byte small_order_keys[][ED448_PUB_KEY_SIZE] = {
|
|
/* identity (y = 1), sign 0 */
|
|
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00},
|
|
/* identity (y = 1), sign bit set */
|
|
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x80},
|
|
/* order 4: y = 0, x-sign 0 */
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00},
|
|
/* order 4: y = 0, x-sign 1 */
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x80},
|
|
/* order 2: y = p - 1, x = 0, sign 0 */
|
|
{0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x00},
|
|
/* order 2: y = p - 1, sign bit set */
|
|
{0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x80},
|
|
/* non-canonical y = p (decodes to y = 0), sign 0 */
|
|
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x00},
|
|
/* non-canonical y = p, sign bit set */
|
|
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x80},
|
|
/* non-canonical y = p + 1 (decodes to y = 1), sign 0 */
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x00},
|
|
/* non-canonical y = p + 1, sign bit set */
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
0x80},
|
|
};
|
|
/* Arbitrary signature bytes: S = 1 (must be below the Ed448 group
|
|
* order or wc_ed448_verify_msg() returns BAD_FUNC_ARG before the
|
|
* small-order check has a chance to fire). The R bytes do not need
|
|
* to encode a valid curve point for this test - the small-order
|
|
* defence in ed448_verify_msg_final_with_sha() rejects the public
|
|
* key before the R/S verification math runs. */
|
|
static const byte forged_sig[ED448_SIG_SIZE] = {
|
|
/* R: 57 bytes of arbitrary data (last byte 0 to satisfy the
|
|
* spec-mandated zero of byte 56 bits 0-6; sign bit doesn't
|
|
* matter here). */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,
|
|
/* S = 1 */
|
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00
|
|
};
|
|
ed448_key key;
|
|
word32 i;
|
|
word32 num_keys = (word32)(sizeof(small_order_keys) / ED448_PUB_KEY_SIZE);
|
|
|
|
/* (1) Untrusted wc_ed448_import_public must reject every small-order
|
|
* encoding (it runs wc_ed448_check_key as part of the import). */
|
|
for (i = 0; i < num_keys; i++) {
|
|
int rc;
|
|
XMEMSET(&key, 0, sizeof(key));
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
rc = wc_ed448_import_public(small_order_keys[i],
|
|
ED448_PUB_KEY_SIZE, &key);
|
|
if (rc != WC_NO_ERR_TRACE(PUBLIC_KEY_E)) {
|
|
fprintf(stderr, "small_order_keys[%u]: import_public returned %d, "
|
|
"expected PUBLIC_KEY_E\n", (unsigned)i, rc);
|
|
}
|
|
ExpectIntEQ(rc, WC_NO_ERR_TRACE(PUBLIC_KEY_E));
|
|
wc_ed448_free(&key);
|
|
}
|
|
|
|
/* (2) wc_ed448_check_key called directly must also reject. Guards
|
|
* against a refactor that moves the small-order check out of
|
|
* check_key and into the import path: (1) would still pass, but the
|
|
* documented check_key contract would silently regress. */
|
|
for (i = 0; i < num_keys; i++) {
|
|
int rc;
|
|
XMEMSET(&key, 0, sizeof(key));
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
/* trusted = 1 bypasses the import-time check_key call so the
|
|
* direct check_key below is what's under test. */
|
|
ExpectIntEQ(wc_ed448_import_public_ex(small_order_keys[i],
|
|
ED448_PUB_KEY_SIZE, &key, 1), 0);
|
|
rc = wc_ed448_check_key(&key);
|
|
if (rc != WC_NO_ERR_TRACE(PUBLIC_KEY_E)) {
|
|
fprintf(stderr, "small_order_keys[%u]: check_key returned %d, "
|
|
"expected PUBLIC_KEY_E\n", (unsigned)i, rc);
|
|
}
|
|
ExpectIntEQ(rc, WC_NO_ERR_TRACE(PUBLIC_KEY_E));
|
|
wc_ed448_free(&key);
|
|
}
|
|
|
|
/* (3) Even a "trusted" import (which bypasses wc_ed448_check_key)
|
|
* must not let wc_ed448_verify_msg accept a forged signature against
|
|
* an identity public key. Test both the canonical encoding (y = 1,
|
|
* small_order_keys[0]) and the non-canonical encoding (y = p + 1,
|
|
* small_order_keys[8]) so the verify-side check is exercised against
|
|
* the canonical-form bypass route, not just the byte-for-byte
|
|
* identity. */
|
|
{
|
|
static const word32 identity_indices[] = { 0, 8 };
|
|
const char* msg = "forged message";
|
|
word32 j;
|
|
|
|
for (j = 0;
|
|
j < sizeof(identity_indices)/sizeof(identity_indices[0]);
|
|
j++) {
|
|
word32 idx = identity_indices[j];
|
|
int verify_result = 1;
|
|
int rc;
|
|
|
|
XMEMSET(&key, 0, sizeof(key));
|
|
ExpectIntEQ(wc_ed448_init(&key), 0);
|
|
ExpectIntEQ(wc_ed448_import_public_ex(small_order_keys[idx],
|
|
ED448_PUB_KEY_SIZE, &key, 1), 0);
|
|
rc = wc_ed448_verify_msg(forged_sig, sizeof(forged_sig),
|
|
(const byte*)msg, (word32)XSTRLEN(msg), &verify_result,
|
|
&key, NULL, 0);
|
|
if (rc != WC_NO_ERR_TRACE(BAD_FUNC_ARG) || verify_result != 0) {
|
|
fprintf(stderr, "verify_msg with identity-equiv "
|
|
"small_order_keys[%u]: rc=%d verify_result=%d "
|
|
"(expected BAD_FUNC_ARG and 0)\n",
|
|
(unsigned)idx, rc, verify_result);
|
|
}
|
|
ExpectIntEQ(rc, WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(verify_result, 0);
|
|
wc_ed448_free(&key);
|
|
}
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|