1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/tests/api/test_curve448.c
2026-09-10 11:55:29 -06:00

1442 lines
55 KiB
C

/* test_curve448.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/curve448.h>
#include <wolfssl/wolfcrypt/types.h>
#ifdef WOLF_CRYPTO_CB
#include <wolfssl/wolfcrypt/cryptocb.h>
#endif
#include <tests/api/api.h>
#include <tests/api/test_curve448.h>
/*
* Testing wc_curve448_make_key
*/
int test_wc_curve448_make_key(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
int keysize = 0;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntEQ(keysize = wc_curve448_size(&key), CURVE448_KEY_SIZE);
ExpectIntEQ(wc_curve448_make_key(&rng, keysize, &key), 0);
/* test bad cases */
ExpectIntEQ(wc_curve448_make_key(NULL, 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_make_key(&rng, keysize, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_make_key(NULL, keysize, &key),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_make_key(&rng, 0, &key),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_make_key */
/*
* Testing test_wc_curve448_shared_secret_ex
*/
int test_wc_curve448_shared_secret_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key private_key;
curve448_key public_key;
WC_RNG rng;
byte out[CURVE448_KEY_SIZE];
word32 outLen = sizeof(out);
int endian = EC448_BIG_ENDIAN;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&private_key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &private_key), 0);
ExpectIntEQ(wc_curve448_init(&public_key), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &public_key), 0);
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, out,
&outLen, endian), 0);
/* test bad cases */
ExpectIntEQ(wc_curve448_shared_secret_ex(NULL, NULL, NULL, 0, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_shared_secret_ex(NULL, &public_key, out, &outLen,
endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, NULL, out, &outLen,
endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, NULL,
&outLen, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, out,
NULL, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
outLen = outLen - 2;
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, out,
&outLen, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&private_key);
wc_curve448_free(&public_key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_shared_secret_ex */
/*
* Testing that wc_curve448_shared_secret_ex rejects an all-zero shared
* secret (RFC 7748 section 6.2). This is the default behavior; users that
* need the legacy behavior can opt out with WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK.
*/
int test_wc_curve448_shared_secret_zero_check(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) && \
defined(HAVE_CURVE448_SHARED_SECRET) && \
!defined(WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK)
curve448_key private_key;
curve448_key public_key;
WC_RNG rng;
byte out[CURVE448_KEY_SIZE];
word32 outLen = sizeof(out);
/* All-zero public key is a low-order point that yields an all-zero
* shared secret for any private key. */
byte zero_pub[CURVE448_PUB_KEY_SIZE];
XMEMSET(&rng, 0, sizeof(WC_RNG));
XMEMSET(zero_pub, 0, sizeof(zero_pub));
ExpectIntEQ(wc_curve448_init(&private_key), 0);
ExpectIntEQ(wc_curve448_init(&public_key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &private_key), 0);
ExpectIntEQ(wc_curve448_import_public_ex(zero_pub, sizeof(zero_pub),
&public_key, EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key, out,
&outLen, EC448_BIG_ENDIAN),
WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&private_key);
wc_curve448_free(&public_key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_shared_secret_zero_check */
/*
* Testing test_wc_curve448_export_public_ex
*/
int test_wc_curve448_export_public_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
WC_RNG rng;
curve448_key key;
curve448_key unset;
curve448_key pubOnly;
byte out[CURVE448_KEY_SIZE];
byte pubOut[CURVE448_KEY_SIZE];
word32 outLen = sizeof(out);
word32 pubOutLen = sizeof(pubOut);
int endian = EC448_BIG_ENDIAN;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_curve448_init(&unset), 0);
ExpectIntEQ(wc_curve448_init(&pubOnly), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntEQ(wc_curve448_export_public(&key, out, &outLen), 0);
ExpectIntEQ(wc_curve448_export_public_ex(&key, out, &outLen, endian), 0);
/* a key holding only a public component exports it unchanged */
ExpectIntEQ(wc_curve448_import_public(out, outLen, &pubOnly), 0);
ExpectIntEQ(wc_curve448_export_public_ex(&pubOnly, pubOut, &pubOutLen,
endian), 0);
ExpectIntEQ(pubOutLen, CURVE448_PUB_KEY_SIZE);
ExpectIntEQ(XMEMCMP(out, pubOut, CURVE448_PUB_KEY_SIZE), 0);
/* test bad cases */
ExpectIntEQ(wc_curve448_export_public_ex(NULL, NULL, NULL, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_public_ex(NULL, out, &outLen, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_public_ex(&key, NULL, &outLen, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_public_ex(&key, out, NULL, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* no private or public key set to export */
ExpectIntEQ(wc_curve448_export_public(&unset, out, &outLen),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_export_public_ex(&unset, out, &outLen, endian),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
outLen = outLen - 2;
ExpectIntEQ(wc_curve448_export_public_ex(&key, out, &outLen, endian),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
wc_curve448_free(&unset);
wc_curve448_free(&pubOnly);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_export_public_ex */
/*
* Testing test_wc_curve448_export_private_raw_ex
*/
int test_wc_curve448_export_private_raw_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
byte out[CURVE448_KEY_SIZE];
word32 outLen = sizeof(out);
int endian = EC448_BIG_ENDIAN;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
/* Reject export when private key not set (privSet == 0). */
ExpectIntEQ(wc_curve448_export_private_raw_ex(&key, out, &outLen, endian),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* test bad cases */
ExpectIntEQ(wc_curve448_export_private_raw_ex(NULL, NULL, NULL, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_private_raw_ex(NULL, out, &outLen, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_private_raw_ex(&key, NULL, &outLen, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_export_private_raw_ex(&key, out, NULL, endian),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Populate the key, then exercise the buffer-too-small path. */
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
outLen = CURVE448_KEY_SIZE - 1;
ExpectIntEQ(wc_curve448_export_private_raw_ex(&key, out, &outLen, endian),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_export_private_raw_ex */
/*
* Testing test_curve448_export_key_raw
*/
int test_wc_curve448_export_key_raw(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
byte priv[CURVE448_KEY_SIZE];
byte pub[CURVE448_KEY_SIZE];
word32 privSz = sizeof(priv);
word32 pubSz = sizeof(pub);
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntEQ(wc_curve448_export_private_raw(&key, priv, &privSz), 0);
ExpectIntEQ(wc_curve448_export_public(&key, pub, &pubSz), 0);
ExpectIntEQ(wc_curve448_export_key_raw(&key, priv, &privSz, pub, &pubSz),
0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_import_private_raw_ex */
/*
* Testing test_wc_curve448_import_private_raw_ex
*/
int test_wc_curve448_import_private_raw_ex(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
byte priv[CURVE448_KEY_SIZE];
byte pub[CURVE448_KEY_SIZE];
word32 privSz = sizeof(priv);
word32 pubSz = sizeof(pub);
int endian = EC448_BIG_ENDIAN;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntEQ(wc_curve448_export_private_raw(&key, priv, &privSz), 0);
ExpectIntEQ(wc_curve448_export_public(&key, pub, &pubSz), 0);
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz,
&key, endian), 0);
/* test bad cases */
ExpectIntEQ(wc_curve448_import_private_raw_ex(NULL, 0, NULL, 0, NULL, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_import_private_raw_ex(NULL, privSz, pub, pubSz,
&key, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, privSz, NULL, pubSz,
&key, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz,
NULL, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, 0, pub, pubSz,
&key, endian), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, privSz, pub, 0,
&key, endian), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz,
&key, EC448_LITTLE_ENDIAN), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_import_private_raw_ex */
/*
* Testing test_wc_curve448_import_private
*/
int test_wc_curve448_import_private(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
byte priv[CURVE448_KEY_SIZE];
word32 privSz = sizeof(priv);
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntEQ(wc_curve448_export_private_raw(&key, priv, &privSz), 0);
ExpectIntEQ(wc_curve448_import_private(priv, privSz, &key), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_import */
/*
* Testing wc_curve448_init and wc_curve448_free.
*/
int test_wc_curve448_init(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
/* Test bad args for wc_curve448_init */
ExpectIntEQ(wc_curve448_init(&key), 0);
/* Test bad args for wc_curve448_init */
ExpectIntEQ(wc_curve448_init(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Test good args for wc_curve_448_free */
wc_curve448_free(&key);
/* Test bad args for wc_curve448_free */
wc_curve448_free(NULL);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_init and wc_curve_448_free */
/*
* Testing test_wc_curve448_size.
*/
int test_wc_curve448_size(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
ExpectIntEQ(wc_curve448_init(&key), 0);
/* Test good args for wc_curve448_size */
ExpectIntEQ(wc_curve448_size(&key), CURVE448_KEY_SIZE);
/* Test bad args for wc_curve448_size */
ExpectIntEQ(wc_curve448_size(NULL), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_size */
/*
* Testing wc_Curve448PrivateKeyToDer
*/
int test_wc_Curve448PrivateKeyToDer(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) && \
(defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
byte output[ONEK_BUF];
curve448_key curve448PrivKey;
WC_RNG rng;
word32 inLen;
XMEMSET(&curve448PrivKey, 0, sizeof(curve448PrivKey));
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&curve448PrivKey), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &curve448PrivKey),
0);
inLen = (word32)sizeof(output);
/* Bad Cases */
ExpectIntEQ(wc_Curve448PrivateKeyToDer(NULL, NULL, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_Curve448PrivateKeyToDer(NULL, output, inLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_Curve448PrivateKeyToDer(&curve448PrivKey, output, 0),
WC_NO_ERR_TRACE(BUFFER_E));
/* Good cases */
/* length only */
ExpectIntGT(wc_Curve448PrivateKeyToDer(&curve448PrivKey, NULL, 0), 0);
ExpectIntGT(wc_Curve448PrivateKeyToDer(&curve448PrivKey, output, inLen), 0);
/* Bad Cases */
ExpectIntEQ(wc_Curve448PublicKeyToDer(NULL, NULL, 0, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_Curve448PublicKeyToDer(NULL, output, inLen, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_Curve448PublicKeyToDer(&curve448PrivKey, output, 0, 0),
WC_NO_ERR_TRACE(BUFFER_E));
ExpectIntEQ(wc_Curve448PublicKeyToDer(&curve448PrivKey, output, 0, 1),
WC_NO_ERR_TRACE(BUFFER_E));
/* Good cases */
/* length only */
ExpectIntGT(wc_Curve448PublicKeyToDer(&curve448PrivKey, NULL, 0, 0), 0);
ExpectIntGT(wc_Curve448PublicKeyToDer(&curve448PrivKey, NULL, 0, 1), 0);
ExpectIntGT(wc_Curve448PublicKeyToDer(&curve448PrivKey, output, inLen, 0),
0);
ExpectIntGT(wc_Curve448PublicKeyToDer(&curve448PrivKey, output, inLen, 1),
0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&curve448PrivKey);
#endif
return EXPECT_RESULT();
} /* End wc_Curve448PrivateKeyToDer*/
/*
* RFC 5958: private only path must create version=v1 (0). Curve448 has no
* public API to create bundled key. Only test private key path. */
int test_wc_Curve448PrivateKeyToDer_oneasymkey_version(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) && \
defined(HAVE_CURVE448_KEY_IMPORT)
curve448_key key;
curve448_key key2;
WC_RNG rng;
byte ref[256]; /* reference DER (private only) */
byte rt[256]; /* re-export target for memcmp */
int refSz = 0;
int rtSz = 0;
word32 idx = 0;
XMEMSET(&key, 0, sizeof(key));
XMEMSET(&key2, 0, sizeof(key2));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_curve448_init(&key2), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
ExpectIntGT(refSz = wc_Curve448PrivateKeyToDer(&key, ref,
(word32)sizeof(ref)), 0);
ExpectIntEQ(test_pkcs8_get_version_byte(ref, (word32)refSz), 0);
idx = 0;
ExpectIntEQ(wc_Curve448PrivateKeyDecode(ref, &idx, &key2,
(word32)refSz), 0);
ExpectIntGT(rtSz = wc_Curve448PrivateKeyToDer(&key2, rt,
(word32)sizeof(rt)), 0);
ExpectIntEQ(rtSz, refSz);
ExpectIntEQ(XMEMCMP(ref, rt, (size_t)refSz), 0);
wc_curve448_free(&key);
wc_curve448_free(&key2);
wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
/*
* MC/DC decision coverage for wolfcrypt/src/curve448.c. Split into several
* small functions (rather than one large one) to keep each function's own
* locals small, matching the lesson learned on the ecc.c/curve25519.c MC/DC
* waves (a single large function tripped a stack-corrupting crash under
* -fcoverage-mcdc + -O0).
*/
/*
* wc_curve448_make_pub argument-check decisions (never called directly by
* the pre-existing tests): the (pub == NULL || priv == NULL) OR and the
* (public_size != PUB || private_size != KEY) OR, each operand independently.
*/
int test_wc_curve448_make_pub_argchecks(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448)
curve448_key key;
WC_RNG rng;
byte pub[CURVE448_PUB_KEY_SIZE];
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
/* all-false: valid direct call. */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pub), pub,
(int)sizeof(key.k), key.k), 0);
/* pub == NULL || priv == NULL: each operand's TRUE side (the other
* kept valid so the OR does not already short-circuit). */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pub), NULL,
(int)sizeof(key.k), key.k), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pub), pub,
(int)sizeof(key.k), NULL), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* public_size != PUB || private_size != KEY: each operand's TRUE side. */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pub) - 1, pub,
(int)sizeof(key.k), key.k), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pub), pub,
(int)sizeof(key.k) - 1, key.k), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_make_pub_argchecks */
/*
* wc_curve448_check_public little-endian branch: NULL/size guards, the
* (i == 0 && (pub[0] == 0 || pub[0] == 1)) low-value compound, the
* (i == 28 && pub[28] == 0xff) -> p+1 (non-canonical 1) rejection, and the
* (i == 28 && pub[28] == 0xfe) -> (i == 0 && pub[0] >= 0xfe) high-value
* compound, plus their false sides.
*/
int test_wc_curve448_check_public_le(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)
byte buf[CURVE448_PUB_KEY_SIZE];
/* pub == NULL. */
ExpectIntEQ(wc_curve448_check_public(NULL, CURVE448_PUB_KEY_SIZE,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* pubSz == 0. */
ExpectIntEQ(wc_curve448_check_public(buf, 0, EC448_LITTLE_ENDIAN),
WC_NO_ERR_TRACE(BUFFER_E));
/* pubSz != CURVE448_PUB_KEY_SIZE. */
ExpectIntEQ(wc_curve448_check_public(buf, CURVE448_PUB_KEY_SIZE - 1,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* value == 0: i walks down to 0, pub[0] == 0. */
XMEMSET(buf, 0, sizeof(buf));
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* value == 1: i walks down to 0, pub[0] == 1. */
XMEMSET(buf, 0, sizeof(buf));
buf[0] = 1;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* i reaches 0 but pub[0] is neither 0 nor 1: low compound false side,
* and a small value so the order checks also pass -> valid (0). */
XMEMSET(buf, 0, sizeof(buf));
buf[0] = 2;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* 2^448-1: bytes 55..28 all 0xff -> loop stops at i == 28 with
* pub[28] == 0xff. This is the non-canonical encoding of 2^224 and must
* be accepted (RFC 7748 Section 5). */
XMEMSET(buf, 0xff, sizeof(buf));
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* p+1 = 2^448 - 2^224: pub[55..28] == 0xff, pub[27..0] == 0x00, the
* non-canonical encoding of the low-order value 1 -> reject. */
XMEMSET(buf, 0x00, sizeof(buf));
XMEMSET(buf + 28, 0xff, sizeof(buf) - 28);
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* p+2: as p+1 with pub[0] == 1, non-canonical 2 -> accepted. */
buf[0] = 0x01;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* p+1 shape but a middle byte breaks the zero run: not p+1 -> accepted. */
buf[0] = 0x00;
buf[10] = 0x01;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* p-1 = fe ff[27] fe ff[27]: the low-order point u = -1 -> reject. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[28] = 0xfe;
buf[0] = 0xfe;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* pub[28] == 0xfe with the remaining low bytes all 0xff and
* pub[0] >= 0xfe -> inner reject fires. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[28] = 0xfe;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* pub[28] == 0xfe but a lower byte breaks the 0xff run (pub[10] = 0), so
* the inner ">= 0xfe at i == 0" reject does NOT fire: false side -> 0. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[28] = 0xfe;
buf[10] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* i still lands on 28 (bytes 55..29 all 0xff), but pub[28] is neither
* 0xff nor 0xfe: independence pair (false side) for the "pub[28] ==
* 0xfe" operand of the high-value compound -> no inner check, valid. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[28] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
/* pub[28] == 0xfe (enters the inner check, i lands on 0 with the low
* bytes still all 0xff) but pub[0] is below the 0xfe threshold:
* independence pair (false side) for the inner "pub[0] >= 0xfe"
* operand -> valid. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[28] = 0xfe;
buf[0] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_LITTLE_ENDIAN), 0);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_check_public_le */
/*
* wc_curve448_check_public big-endian branch (the else-side mirror of the
* little-endian decisions above).
*/
int test_wc_curve448_check_public_be(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)
byte buf[CURVE448_PUB_KEY_SIZE];
/* value == 0: i walks up to SIZE-1, pub[SIZE-1] == 0. */
XMEMSET(buf, 0, sizeof(buf));
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* value == 1: pub[SIZE-1] == 1. */
XMEMSET(buf, 0, sizeof(buf));
buf[CURVE448_PUB_KEY_SIZE - 1] = 1;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* i reaches SIZE-1 but value neither 0 nor 1: low compound false -> 0. */
XMEMSET(buf, 0, sizeof(buf));
buf[CURVE448_PUB_KEY_SIZE - 1] = 2;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* 2^448-1: bytes 0..27 all 0xff -> loop stops at i == 27 with
* pub[27] == 0xff. Non-canonical encoding of 2^224 -> accepted. */
XMEMSET(buf, 0xff, sizeof(buf));
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* p+1: pub[0..27] == 0xff, pub[28..55] == 0x00 -> non-canonical 1,
* reject. */
XMEMSET(buf, 0xff, sizeof(buf));
XMEMSET(buf + 28, 0x00, sizeof(buf) - 28);
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* p+2: as p+1 with pub[55] == 1 -> accepted. */
buf[CURVE448_PUB_KEY_SIZE - 1] = 0x01;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* p+1 shape but a middle byte breaks the zero run -> accepted. */
buf[CURVE448_PUB_KEY_SIZE - 1] = 0x00;
buf[45] = 0x01;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* p-1: ff[27] fe ff[27] fe -> the low-order point u = -1, reject. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[27] = 0xfe;
buf[CURVE448_PUB_KEY_SIZE - 1] = 0xfe;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* pub[27] == 0xfe, remaining tail all 0xff, pub[SIZE-1] >= 0xfe ->
* inner reject fires. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[27] = 0xfe;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* pub[27] == 0xfe but a tail byte breaks the 0xff run (pub[54] = 0):
* inner reject does NOT fire -> 0. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[27] = 0xfe;
buf[CURVE448_PUB_KEY_SIZE - 2] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* i still lands on 27 (bytes 0..26 all 0xff), but pub[27] is neither
* 0xff nor 0xfe: independence pair (false side) for the "pub[27] ==
* 0xfe" operand of the high-value compound -> no inner check, valid. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[27] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
/* pub[27] == 0xfe (enters the inner check, i lands on SIZE-1 with the
* tail still all 0xff) but pub[SIZE-1] is below the 0xfe threshold:
* independence pair (false side) for the inner "pub[SIZE-1] >= 0xfe"
* operand -> valid. */
XMEMSET(buf, 0xff, sizeof(buf));
buf[27] = 0xfe;
buf[CURVE448_PUB_KEY_SIZE - 1] = 0x00;
ExpectIntEQ(wc_curve448_check_public(buf, sizeof(buf),
EC448_BIG_ENDIAN), 0);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_check_public_be */
/*
* wc_curve448_shared_secret_ex populated-key compound decision:
* (!private_key->privSet || !public_key->pubSet), each operand's TRUE side
* individually against otherwise-valid, non-NULL key structs, plus the
* little-endian output branch as the all-false side.
*/
int test_wc_curve448_shared_secret_keyset_checks(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_SHARED_SECRET)
curve448_key priv;
curve448_key pub;
curve448_key unset_priv;
curve448_key unset_pub;
WC_RNG rng;
byte out[CURVE448_KEY_SIZE];
word32 outLen;
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&priv), 0);
ExpectIntEQ(wc_curve448_init(&pub), 0);
ExpectIntEQ(wc_curve448_init(&unset_priv), 0);
ExpectIntEQ(wc_curve448_init(&unset_pub), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &priv), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &pub), 0);
/* !privSet TRUE (fresh unset_priv), pub valid. */
outLen = sizeof(out);
ExpectIntEQ(wc_curve448_shared_secret_ex(&unset_priv, &pub, out, &outLen,
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* !pubSet TRUE (fresh unset_pub), priv valid. */
outLen = sizeof(out);
ExpectIntEQ(wc_curve448_shared_secret_ex(&priv, &unset_pub, out, &outLen,
EC448_BIG_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* all-false: valid call, little-endian output branch. */
outLen = sizeof(out);
ExpectIntEQ(wc_curve448_shared_secret_ex(&priv, &pub, out, &outLen,
EC448_LITTLE_ENDIAN), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&priv);
wc_curve448_free(&pub);
wc_curve448_free(&unset_priv);
wc_curve448_free(&unset_pub);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_shared_secret_keyset_checks */
/*
* wc_curve448_import_public_ex argument checks: the (key == NULL || in ==
* NULL) compound each operand, the inLen size check, and both endian
* branches as the all-false side.
*/
int test_wc_curve448_import_public_ex_argchecks(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)
curve448_key key;
byte in[CURVE448_PUB_KEY_SIZE];
XMEMSET(in, 7, sizeof(in));
ExpectIntEQ(wc_curve448_init(&key), 0);
/* key == NULL || in == NULL: each operand's TRUE side. */
ExpectIntEQ(wc_curve448_import_public_ex(in, sizeof(in), NULL,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_curve448_import_public_ex(NULL, sizeof(in), &key,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* inLen != CURVE448_PUB_KEY_SIZE. */
ExpectIntEQ(wc_curve448_import_public_ex(in, sizeof(in) - 1, &key,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* all-false, both endians (LE XMEMCPY branch + BE byte-reverse loop). */
ExpectIntEQ(wc_curve448_import_public_ex(in, sizeof(in), &key,
EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_import_public_ex(in, sizeof(in), &key,
EC448_BIG_ENDIAN), 0);
ExpectIntEQ(wc_curve448_import_public(in, sizeof(in), &key), 0);
wc_curve448_free(&key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_import_public_ex_argchecks */
/*
* Little-endian export/import branches (the non-BIG_ENDIAN XMEMCPY sides of
* wc_curve448_export_private_raw_ex/export_public_ex/import_private_ex) and
* the wc_curve448_export_public_ex "!pubSet -> internal make_pub" branch.
*/
int test_wc_curve448_export_import_endian(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) && \
defined(HAVE_CURVE448_KEY_IMPORT)
curve448_key key;
curve448_key imp;
WC_RNG rng;
byte priv[CURVE448_KEY_SIZE] = {0};
byte pub[CURVE448_PUB_KEY_SIZE] = {0};
word32 privSz = sizeof(priv);
word32 pubSz = sizeof(pub);
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&key), 0);
ExpectIntEQ(wc_curve448_init(&imp), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0);
/* Little-endian export branches. */
ExpectIntEQ(wc_curve448_export_private_raw_ex(&key, priv, &privSz,
EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_export_public_ex(&key, pub, &pubSz,
EC448_LITTLE_ENDIAN), 0);
/* Little-endian import branch (+ clamp). */
ExpectIntEQ(wc_curve448_import_private_ex(priv, privSz, &imp,
EC448_LITTLE_ENDIAN), 0);
/* export_public_ex with !pubSet: a private-only key forces the internal
* wc_curve448_make_pub path that computes and sets key->p. */
wc_curve448_free(&imp);
ExpectIntEQ(wc_curve448_init(&imp), 0);
ExpectIntEQ(wc_curve448_import_private_ex(priv, privSz, &imp,
EC448_LITTLE_ENDIAN), 0);
pubSz = sizeof(pub);
ExpectIntEQ(wc_curve448_export_public_ex(&imp, pub, &pubSz,
EC448_BIG_ENDIAN), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&key);
wc_curve448_free(&imp);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_export_import_endian */
/* Cross-check make_pub, generic and keygen: public keys must match and a
* shared secret must round trip. */
/* The keys are built with wc_curve448_init (INVALID_DEVID), so under CB-only
* the software path is stripped and wc_curve448_make_key only dispatches when
* WOLF_CRYPTO_CB_FIND can route to a registered device. */
int test_wc_curve448_make_pub_generic(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_SHARED_SECRET) && \
(!defined(WOLF_CRYPTO_CB_ONLY_CURVE448) || defined(WOLF_CRYPTO_CB_FIND))
curve448_key keyA;
curve448_key keyB;
WC_RNG rng;
byte pubM[CURVE448_PUB_KEY_SIZE];
byte pubG[CURVE448_PUB_KEY_SIZE];
const byte base5[CURVE448_KEY_SIZE] = { 5 };
byte genAB[CURVE448_PUB_KEY_SIZE];
byte ssAB[CURVE448_PUB_KEY_SIZE];
byte ssBA[CURVE448_PUB_KEY_SIZE];
word32 ssABLen = (word32)sizeof(ssAB);
word32 ssBALen = (word32)sizeof(ssBA);
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve448_init(&keyA), 0);
ExpectIntEQ(wc_curve448_init(&keyB), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &keyA), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &keyB), 0);
/* make_pub from the private scalar must match the keygen public point */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pubM), pubM,
(int)sizeof(keyA.k), keyA.k), 0);
ExpectBufEQ(pubM, keyA.p, CURVE448_PUB_KEY_SIZE);
/* generic against base point 5 is the same operation as make_pub */
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), base5), 0);
ExpectBufEQ(pubG, pubM, CURVE448_PUB_KEY_SIZE);
/* generic against B's public point must equal the A-B shared secret,
* proving generic actually uses the supplied base point */
ExpectIntEQ(wc_curve448_generic((int)sizeof(genAB), genAB,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(keyB.p), keyB.p), 0);
ExpectIntEQ(wc_curve448_shared_secret_ex(&keyA, &keyB, ssAB, &ssABLen,
EC448_LITTLE_ENDIAN), 0);
ExpectBufEQ(genAB, ssAB, CURVE448_PUB_KEY_SIZE);
/* shared secret must agree both ways, proving the generated keys are
* mutually consistent (a degenerate result is rejected by shared_secret) */
ExpectIntEQ(wc_curve448_shared_secret_ex(&keyB, &keyA, ssBA, &ssBALen,
EC448_LITTLE_ENDIAN), 0);
ExpectBufEQ(ssBA, ssAB, CURVE448_PUB_KEY_SIZE);
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
/* an all-zero result (small-order basepoint) must be rejected, matching
* wc_curve448_shared_secret_ex */
XMEMSET(pubG, 0, sizeof(pubG));
{
byte baseZero[CURVE448_KEY_SIZE];
XMEMSET(baseZero, 0, sizeof(baseZero));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(baseZero), baseZero),
WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
}
#endif
/* argument checks on the new generic API */
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), NULL,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), NULL, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), NULL),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG) - 1, pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k) - 1, keyA.k, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5) - 1, base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
/* unclamped scalars must be rejected: low bits set, then top bit clear */
keyA.k[0] |= 0x01;
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pubM), pubM,
(int)sizeof(keyA.k), keyA.k), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
keyA.k[0] &= 0xfc;
keyA.k[CURVE448_KEY_SIZE-1] &= 0x7f;
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pubM), pubM,
(int)sizeof(keyA.k), keyA.k), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base5), base5),
WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
keyA.k[CURVE448_KEY_SIZE-1] |= 0x80;
/* restored key must work again */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pubM), pubM,
(int)sizeof(keyA.k), keyA.k), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve448_free(&keyA);
wc_curve448_free(&keyB);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_make_pub_generic */
/* Test Curve448 keygen/shared secret routed through a crypto callback
* (CryptoCb) device. */
/* The spy services ops by re-entering the software API, which is stripped
* under CB-only unless WOLF_CRYPTO_CB_FIND can route back to a device. */
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_CURVE448) && \
defined(HAVE_CURVE448_SHARED_SECRET) && !defined(WC_NO_RNG) && \
(!defined(WOLF_CRYPTO_CB_ONLY_CURVE448) || defined(WOLF_CRYPTO_CB_FIND))
typedef struct curve448SpyCtx {
int kgSeen;
int ssSeen;
int mpSeen;
int genSeen;
int decline;
int forceErr;
int zeroSecret;
} curve448SpyCtx;
/* Spy device: services Curve448 keygen/shared secret in software (devId
* cleared) and counts each; declines everything else. */
static int curve448_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
curve448SpyCtx* spy = (curve448SpyCtx*)ctx;
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
(void)devIdArg;
if (info == NULL || spy == NULL) {
return BAD_FUNC_ARG;
}
if (info->algo_type == WC_ALGO_TYPE_PK) {
if (info->pk.type == WC_PK_TYPE_CURVE448_KEYGEN) {
int save = info->pk.curve448kg.key->devId;
spy->kgSeen++;
if (spy->decline)
return ret;
if (spy->forceErr)
return WC_NO_ERR_TRACE(WC_HW_E);
info->pk.curve448kg.key->devId = INVALID_DEVID;
ret = wc_curve448_make_key(info->pk.curve448kg.rng,
info->pk.curve448kg.size, info->pk.curve448kg.key);
info->pk.curve448kg.key->devId = save;
}
if (info->pk.type == WC_PK_TYPE_CURVE448_MAKE_PUB) {
/* count, then decline so the software path produces the point */
spy->mpSeen++;
}
if (info->pk.type == WC_PK_TYPE_CURVE448_GENERIC) {
spy->genSeen++;
if (spy->zeroSecret) {
/* misbehaving device: all-zero point with success rc */
XMEMSET(info->pk.curve448generic.pub, 0,
CURVE448_PUB_KEY_SIZE);
return 0;
}
/* otherwise decline so the software path produces the point */
}
if (info->pk.type == WC_PK_TYPE_CURVE448) {
int save = info->pk.curve448.private_key->devId;
spy->ssSeen++;
if (spy->decline)
return ret;
if (spy->forceErr)
return WC_NO_ERR_TRACE(WC_HW_E);
if (spy->zeroSecret) {
/* misbehaving device: all-zero secret with success rc */
XMEMSET(info->pk.curve448.out, 0, CURVE448_PUB_KEY_SIZE);
*info->pk.curve448.outlen = CURVE448_PUB_KEY_SIZE;
return 0;
}
info->pk.curve448.private_key->devId = INVALID_DEVID;
ret = wc_curve448_shared_secret_ex(
info->pk.curve448.private_key, info->pk.curve448.public_key,
info->pk.curve448.out, info->pk.curve448.outlen,
info->pk.curve448.endian);
info->pk.curve448.private_key->devId = save;
}
}
return ret;
}
#endif
int test_wc_curve448_cryptocb(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_CURVE448) && \
defined(HAVE_CURVE448_SHARED_SECRET) && !defined(WC_NO_RNG) && \
(!defined(WOLF_CRYPTO_CB_ONLY_CURVE448) || defined(WOLF_CRYPTO_CB_FIND))
int devId = 4485;
curve448SpyCtx spy;
WC_RNG rng;
curve448_key keyB;
byte ssAB[CURVE448_PUB_KEY_SIZE];
byte ssBA[CURVE448_PUB_KEY_SIZE];
word32 ssABLen = (word32)sizeof(ssAB);
word32 ssBALen = (word32)sizeof(ssBA);
#ifndef WC_NO_CONSTRUCTORS
int ret = 0;
curve448_key* keyA = NULL;
#else
curve448_key keyA_stack;
curve448_key* keyA = &keyA_stack;
#endif
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(&spy, 0, sizeof(spy));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, curve448_test_crypto_cb,
&spy), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
#ifndef WC_NO_CONSTRUCTORS
/* exercise the new constructor path */
ExpectNotNull(keyA = wc_curve448_new(HEAP_HINT, devId, &ret));
ExpectIntEQ(ret, 0);
#else
ExpectIntEQ(wc_curve448_init_ex(keyA, HEAP_HINT, devId), 0);
#endif
ExpectIntEQ(wc_curve448_init_ex(&keyB, HEAP_HINT, devId), 0);
/* keygen routes through the device callback */
if (keyA != NULL) {
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, keyA), 0);
}
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &keyB), 0);
ExpectIntGE(spy.kgSeen, 2);
/* shared secret routes through the device callback both ways */
if (keyA != NULL) {
ExpectIntEQ(wc_curve448_shared_secret_ex(keyA, &keyB, ssAB, &ssABLen,
EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_shared_secret_ex(&keyB, keyA, ssBA, &ssBALen,
EC448_LITTLE_ENDIAN), 0);
ExpectBufEQ(ssAB, ssBA, CURVE448_PUB_KEY_SIZE);
}
ExpectIntGE(spy.ssSeen, 2);
#ifndef WOLF_CRYPTO_CB_ONLY_CURVE448
/* device declines: dispatch is seen, software fallback must succeed */
spy.decline = 1;
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &keyB), 0);
ExpectIntGE(spy.kgSeen, 3);
if (keyA != NULL) {
ssABLen = (word32)sizeof(ssAB);
ExpectIntEQ(wc_curve448_shared_secret_ex(keyA, &keyB, ssAB, &ssABLen,
EC448_LITTLE_ENDIAN), 0);
}
ExpectIntGE(spy.ssSeen, 3);
spy.decline = 0;
#endif
/* device errors: the error must propagate, not fall back to software */
spy.forceErr = 1;
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &keyB),
WC_NO_ERR_TRACE(WC_HW_E));
if (keyA != NULL) {
ssABLen = (word32)sizeof(ssAB);
ExpectIntEQ(wc_curve448_shared_secret_ex(keyA, &keyB, ssAB, &ssABLen,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(WC_HW_E));
}
spy.forceErr = 0;
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
/* device returns an all-zero secret: wrapper must reject it */
spy.zeroSecret = 1;
if (keyA != NULL) {
ssABLen = (word32)sizeof(ssAB);
ExpectIntEQ(wc_curve448_shared_secret_ex(keyA, &keyB, ssAB, &ssABLen,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
}
spy.zeroSecret = 0;
#endif
#if !defined(WOLF_CRYPTO_CB_FIND) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE448)
/* a key bound to no device must not have its private scalar handed to
* whichever device happens to be registered: keygen derives the public
* point in software without dispatching make_pub */
{
curve448_key unbound;
byte pubTmp[CURVE448_PUB_KEY_SIZE];
int mpBefore = spy.mpSeen;
XMEMSET(&unbound, 0, sizeof(unbound));
ExpectIntEQ(wc_curve448_init(&unbound), 0);
ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &unbound),
0);
ExpectIntEQ(spy.mpSeen, mpBefore);
/* the keyless public API has no devId to respect, so it still
* reaches the device */
ExpectIntEQ(wc_curve448_make_pub((int)sizeof(pubTmp), pubTmp,
(int)sizeof(unbound.k), unbound.k), 0);
ExpectIntGT(spy.mpSeen, mpBefore);
/* wc_curve448_generic also has no devId to respect, so it reaches
* the device; a device that answers with an all-zero point must be
* rejected just like the software path's small-order result */
{
const byte base5[CURVE448_KEY_SIZE] = { 5 };
int genBefore = spy.genSeen;
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubTmp), pubTmp,
(int)sizeof(unbound.k), unbound.k, (int)sizeof(base5),
base5), 0);
ExpectIntGT(spy.genSeen, genBefore);
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
spy.zeroSecret = 1;
ExpectIntEQ(wc_curve448_generic((int)sizeof(pubTmp), pubTmp,
(int)sizeof(unbound.k), unbound.k, (int)sizeof(base5),
base5), WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
spy.zeroSecret = 0;
#endif
}
wc_curve448_free(&unbound);
}
#endif
/* constructor arg checks */
ExpectIntEQ(wc_curve448_init_ex(NULL, HEAP_HINT, devId),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
wc_curve448_free(&keyB);
#ifndef WC_NO_CONSTRUCTORS
/* result_code and key_p are both optional */
{
curve448_key* keyC = NULL;
ExpectNotNull(keyC = wc_curve448_new(HEAP_HINT, devId, NULL));
if (keyC != NULL) {
DoExpectIntEQ(wc_curve448_delete(keyC, NULL), 0);
}
}
if (keyA != NULL) {
DoExpectIntEQ(wc_curve448_delete(keyA, &keyA), 0);
ExpectNull(keyA);
}
ExpectIntEQ(wc_curve448_delete(NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#else
wc_curve448_free(keyA);
#endif
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_CryptoCb_UnRegisterDevice(devId);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_cryptocb */
/*
* Non-canonical X448 public values (RFC 7748 Section 5): u in [p, 2^448-1],
* p = 2^448 - 2^224 - 1, must be accepted and processed as if reduced
* modulo p. Private key: RFC 7748 Section 6.2 Alice. Peer u = p+2, p+5 and
* 2^448-1, the non-canonical encodings of 2, 5 and 2^224. Expected shared
* secrets computed with OpenSSL 3.6.3 (pkeyutl -derive); the results must
* also equal those for the canonical encodings. Finally the low-order points
* 1, p-1, p and p+1 must never yield a shared secret.
*/
int test_wc_curve448_shared_secret_noncanonical_kat(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) && \
defined(HAVE_CURVE448_SHARED_SECRET)
static const byte kPriv[CURVE448_KEY_SIZE] = {
0x9a,0x8f,0x49,0x25,0xd1,0x51,0x9f,0x57,
0x75,0xcf,0x46,0xb0,0x4b,0x58,0x00,0xd4,
0xee,0x9e,0xe8,0xba,0xe8,0xbc,0x55,0x65,
0xd4,0x98,0xc2,0x8d,0xd9,0xc9,0xba,0xf5,
0x74,0xa9,0x41,0x97,0x44,0x89,0x73,0x91,
0x00,0x63,0x82,0xa6,0xf1,0x27,0xab,0x1d,
0x9a,0xc2,0xd8,0xc0,0xa5,0x98,0x72,0x6b
};
/* Non-canonical encodings (little-endian). */
static const byte kPubNC[3][CURVE448_PUB_KEY_SIZE] = {
{ /* p + 2 */
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,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
},
{ /* p + 5 */
0x04,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
},
{ /* 2^448 - 1 */
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,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
}
};
/* Canonical encodings of the same values: 2, 5 and 2^224. */
static const byte kPubC[3][CURVE448_PUB_KEY_SIZE] = {
{
0x02,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
},
{
0x05,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,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,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
}
};
static const byte kExpected[3][CURVE448_PUB_KEY_SIZE] = {
{
0x6c,0xbd,0xf8,0x29,0x07,0xd2,0xa3,0xf3,
0xbd,0x7a,0x48,0x68,0xac,0x6a,0xe3,0x54,
0xf9,0x7d,0x60,0xc4,0x78,0xfc,0xac,0x33,
0x38,0x9f,0xea,0xb9,0xf0,0x22,0xa2,0x6c,
0xcd,0x71,0x64,0xa2,0xfb,0x9c,0xfb,0x2b,
0x74,0x07,0xa9,0x24,0xc6,0x26,0x26,0xf7,
0x38,0xa6,0x28,0x69,0xf7,0x17,0xdf,0xad
},
{
0x9b,0x08,0xf7,0xcc,0x31,0xb7,0xe3,0xe6,
0x7d,0x22,0xd5,0xae,0xa1,0x21,0x07,0x4a,
0x27,0x3b,0xd2,0xb8,0x3d,0xe0,0x9c,0x63,
0xfa,0xa7,0x3d,0x2c,0x22,0xc5,0xd9,0xbb,
0xc8,0x36,0x64,0x72,0x41,0xd9,0x53,0xd4,
0x0c,0x5b,0x12,0xda,0x88,0x12,0x0d,0x53,
0x17,0x7f,0x80,0xe5,0x32,0xc4,0x1f,0xa0
},
{
0x66,0xe2,0xe6,0x82,0xb1,0xf8,0xe6,0x8c,
0x80,0x9f,0x1b,0xb3,0xe4,0x06,0xbd,0x82,
0x69,0x21,0xd9,0xc1,0xa5,0xbf,0xbf,0xcb,
0xab,0x7a,0xe7,0x2f,0xee,0xce,0xe6,0x36,
0x60,0xea,0xbd,0x54,0x93,0x4f,0x33,0x82,
0x06,0x1d,0x17,0x60,0x7f,0x58,0x1a,0x90,
0xbd,0xac,0x91,0x7a,0x06,0x49,0x59,0xfb
}
};
/* Low-order points: 1, p-1 (u = -1), p (== 0), p+1 (== 1). */
static const byte kLow[4][CURVE448_PUB_KEY_SIZE] = {
{
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
},
{
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
},
{
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,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
}
};
curve448_key private_key;
curve448_key public_key;
byte out[CURVE448_PUB_KEY_SIZE];
byte outCanon[CURVE448_PUB_KEY_SIZE];
word32 outLen;
int i;
ExpectIntEQ(wc_curve448_init(&private_key), 0);
ExpectIntEQ(wc_curve448_init(&public_key), 0);
ExpectIntEQ(wc_curve448_import_private_ex(kPriv, sizeof(kPriv),
&private_key, EC448_LITTLE_ENDIAN), 0);
for (i = 0; i < 3; i++) {
ExpectIntEQ(wc_curve448_check_public(kPubNC[i], CURVE448_PUB_KEY_SIZE,
EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_import_public_ex(kPubNC[i],
CURVE448_PUB_KEY_SIZE, &public_key, EC448_LITTLE_ENDIAN), 0);
outLen = sizeof(out);
XMEMSET(out, 0, sizeof(out));
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key,
out, &outLen, EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(outLen, CURVE448_PUB_KEY_SIZE);
ExpectBufEQ(out, kExpected[i], CURVE448_PUB_KEY_SIZE);
ExpectIntEQ(wc_curve448_check_public(kPubC[i], CURVE448_PUB_KEY_SIZE,
EC448_LITTLE_ENDIAN), 0);
ExpectIntEQ(wc_curve448_import_public_ex(kPubC[i],
CURVE448_PUB_KEY_SIZE, &public_key, EC448_LITTLE_ENDIAN), 0);
outLen = sizeof(outCanon);
XMEMSET(outCanon, 0, sizeof(outCanon));
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key,
outCanon, &outLen, EC448_LITTLE_ENDIAN), 0);
ExpectBufEQ(outCanon, out, CURVE448_PUB_KEY_SIZE);
}
for (i = 0; i < 4; i++) {
ExpectIntEQ(wc_curve448_check_public(kLow[i], CURVE448_PUB_KEY_SIZE,
EC448_LITTLE_ENDIAN), WC_NO_ERR_TRACE(ECC_BAD_ARG_E));
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
ExpectIntEQ(wc_curve448_import_public_ex(kLow[i],
CURVE448_PUB_KEY_SIZE, &public_key, EC448_LITTLE_ENDIAN), 0);
outLen = sizeof(out);
ExpectIntEQ(wc_curve448_shared_secret_ex(&private_key, &public_key,
out, &outLen, EC448_LITTLE_ENDIAN),
WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E));
#endif
}
wc_curve448_free(&private_key);
wc_curve448_free(&public_key);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve448_shared_secret_noncanonical_kat */