core/crypto/kat/ecdsa_kat.c (530 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include <string.h>
#include "ecc_kat_vectors.h"
#include "ecdsa_kat.h"
#include "asn1/ecc_der_util.h"
#include "common/buffer_util.h"
#include "common/unused.h"
#include "crypto/signature_verification.h"
/**
* Random number generator that will produce a fixed set of random data. This provides a mechanism
* to get a known k value during ECDSA signature generation self-tests.
*/
struct ecdsa_kat_rng {
struct rng_engine base; /**< Base RNG API. */
const uint8_t *data; /**< Buffer containing the data to provide when requested. */
size_t length; /**< Length of the random data. */
};
static int ecdsa_kat_rng_generate_random_buffer (const struct rng_engine *engine, size_t rand_len,
uint8_t *buf)
{
const struct ecdsa_kat_rng *rng = (const struct ecdsa_kat_rng*) engine;
/* Copy up to the maximum provided by the KAT RNG. If more data is requested than is available,
* which won't be the case in properly functioning implementations, the rest of the output
* buffer is left unchanged. */
buffer_copy (rng->data, rng->length, NULL, &rand_len, buf);
return 0;
}
/**
* Initialize a RNG for ECDSA signature generation self-tests.
*/
#define ecdsa_kat_rng_static_init(data_ptr, length_arg) {\
.base = { \
.generate_random_buffer = ecdsa_kat_rng_generate_random_buffer \
}, \
.data = data_ptr, \
.length = length_arg \
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-256 and SHA-256.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_p256_sha256 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P256_SHA256_ECDSA_K, ECC_KEY_LENGTH_256);
uint8_t signature[ECC_DER_P256_ECDSA_MAX_LENGTH] = {0};
int status;
status = ecdsa_sign_message (ecc, hash, HASH_TYPE_SHA256, &rng.base,
ECC_KAT_VECTORS_P256_ECC_PRIVATE_DER, ECC_KAT_VECTORS_P256_ECC_PRIVATE_DER_LEN,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, signature,
sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (signature, sizeof (signature));
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-384 and SHA-384.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_p384_sha384 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P384_SHA384_ECDSA_K, ECC_KEY_LENGTH_384);
uint8_t signature[ECC_DER_P384_ECDSA_MAX_LENGTH] = {0};
int status;
status = ecdsa_sign_message (ecc, hash, HASH_TYPE_SHA384, &rng.base,
ECC_KAT_VECTORS_P384_ECC_PRIVATE_DER, ECC_KAT_VECTORS_P384_ECC_PRIVATE_DER_LEN,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, signature,
sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (signature, sizeof (signature));
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-521 and SHA-512.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_p521_sha512 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P521_SHA512_ECDSA_K, ECC_KEY_LENGTH_521);
uint8_t signature[ECC_DER_P521_ECDSA_MAX_LENGTH] = {0};
int status;
status = ecdsa_sign_message (ecc, hash, HASH_TYPE_SHA512, &rng.base,
ECC_KAT_VECTORS_P521_ECC_PRIVATE_DER, ECC_KAT_VECTORS_P521_ECC_PRIVATE_DER_LEN,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, signature,
sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (signature, sizeof (signature));
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-256 and SHA-256 without
* completing the active hash context.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_hash_p256_sha256 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P256_SHA256_ECDSA_K, ECC_KEY_LENGTH_256);
uint8_t signature[ECC_DER_P256_ECDSA_MAX_LENGTH] = {0};
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha256 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_sign_hash (ecc, hash, &rng.base, ECC_KAT_VECTORS_P256_ECC_PRIVATE_DER,
ECC_KAT_VECTORS_P256_ECC_PRIVATE_DER_LEN, signature, sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
buffer_zeroize (signature, sizeof (signature));
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-384 and SHA-384 without
* completing the active hash context.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_hash_p384_sha384 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P384_SHA384_ECDSA_K, ECC_KEY_LENGTH_384);
uint8_t signature[ECC_DER_P384_ECDSA_MAX_LENGTH] = {0};
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha384 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_sign_hash (ecc, hash, &rng.base, ECC_KAT_VECTORS_P384_ECC_PRIVATE_DER,
ECC_KAT_VECTORS_P384_ECC_PRIVATE_DER_LEN, signature, sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
buffer_zeroize (signature, sizeof (signature));
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature generation using ECC P-521 and SHA-512 without
* completing the active hash context.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_sign_hash_p521_sha512 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P521_SHA512_ECDSA_K, ECC_KEY_LENGTH_521);
uint8_t signature[ECC_DER_P521_ECDSA_MAX_LENGTH] = {0};
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha512 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_sign_hash (ecc, hash, &rng.base, ECC_KAT_VECTORS_P521_ECC_PRIVATE_DER,
ECC_KAT_VECTORS_P521_ECC_PRIVATE_DER_LEN, signature, sizeof (signature));
if (ROT_IS_ERROR (status)) {
goto exit;
}
if ((size_t) status != ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER_LEN) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER, signature, status);
if (status != 0) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
buffer_zeroize (signature, sizeof (signature));
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-256 and SHA-256.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_p256_sha256 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
int status;
status = ecdsa_verify_message (ecc, hash, HASH_TYPE_SHA256, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, ECC_KAT_VECTORS_P256_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P256_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P256_VERIFY_SELF_TEST_FAILED;
}
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-384 and SHA-384.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_p384_sha384 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
int status;
status = ecdsa_verify_message (ecc, hash, HASH_TYPE_SHA384, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, ECC_KAT_VECTORS_P384_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P384_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P384_VERIFY_SELF_TEST_FAILED;
}
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-521 and SHA-512.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_p521_sha512 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
int status;
status = ecdsa_verify_message (ecc, hash, HASH_TYPE_SHA512, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, ECC_KAT_VECTORS_P521_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P521_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P521_VERIFY_SELF_TEST_FAILED;
}
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-256 and SHA-256
* without completing the active hash context.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_hash_p256_sha256 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha256 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_verify_hash (ecc, hash, ECC_KAT_VECTORS_P256_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P256_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P256_VERIFY_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-384 and SHA-384
* without completing the active hash context.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_hash_p384_sha384 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha384 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_verify_hash (ecc, hash, ECC_KAT_VECTORS_P384_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P384_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P384_VERIFY_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification using ECC P-521 and SHA-512
* without completing the active hash context.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc The ECC engine to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_verify_hash_p521_sha512 (const struct ecc_engine *ecc,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
int status;
if (hash == NULL) {
return ECDSA_INVALID_ARGUMENT;
}
status = hash->start_sha512 (hash);
if (status != 0) {
return status;
}
status = hash->update (hash, ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN);
if (status != 0) {
goto exit;
}
status = ecdsa_verify_hash (ecc, hash, ECC_KAT_VECTORS_P521_ECC_PUBLIC_DER,
ECC_KAT_VECTORS_P521_ECC_PUBLIC_DER_LEN, ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER,
ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE_DER_LEN);
if (status == SIG_VERIFICATION_BAD_SIGNATURE) {
status = ECDSA_P521_VERIFY_SELF_TEST_FAILED;
}
exit:
hash->cancel (hash);
return status;
#else
UNUSED (ecc);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature generation directly against an ECC hardware
* driver interface using ECC P-256 and SHA-256.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_sign_p256_sha256 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P256_SHA256_ECDSA_K, ECC_KEY_LENGTH_256);
struct ecc_ecdsa_signature signature = {0};
int status;
status = ecdsa_ecc_hw_sign_message (ecc_hw, hash, HASH_TYPE_SHA256, &rng.base,
ECC_KAT_VECTORS_P256_ECC_PRIVATE, ECC_KEY_LENGTH_256, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, &signature);
if (status != 0) {
goto exit;
}
if (signature.length != ECC_KEY_LENGTH_256) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE.r, signature.r,
ECC_KEY_LENGTH_256);
if (status != 0) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE.s, signature.s,
ECC_KEY_LENGTH_256);
if (status != 0) {
status = ECDSA_P256_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (&signature, sizeof (signature));
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature generation directly against an ECC hardware
* driver interface using ECC P-384 and SHA-384.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_sign_p384_sha384 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P384_SHA384_ECDSA_K, ECC_KEY_LENGTH_384);
struct ecc_ecdsa_signature signature = {0};
int status;
status = ecdsa_ecc_hw_sign_message (ecc_hw, hash, HASH_TYPE_SHA384, &rng.base,
ECC_KAT_VECTORS_P384_ECC_PRIVATE, ECC_KEY_LENGTH_384, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, &signature);
if (status != 0) {
goto exit;
}
if (signature.length != ECC_KEY_LENGTH_384) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE.r, signature.r,
ECC_KEY_LENGTH_384);
if (status != 0) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE.s, signature.s,
ECC_KEY_LENGTH_384);
if (status != 0) {
status = ECDSA_P384_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (&signature, sizeof (signature));
return status;
#else
UNUSED (ecc_hw);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature generation directly against an ECC hardware
* driver interface using ECC P-521 and SHA-512.
*
* It's only necessary to run an ECDSA signature generation self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_sign_p521_sha512 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
struct ecdsa_kat_rng rng =
ecdsa_kat_rng_static_init (ECC_KAT_VECTORS_P521_SHA512_ECDSA_K, ECC_KEY_LENGTH_521);
struct ecc_ecdsa_signature signature = {0};
int status;
status = ecdsa_ecc_hw_sign_message (ecc_hw, hash, HASH_TYPE_SHA512, &rng.base,
ECC_KAT_VECTORS_P521_ECC_PRIVATE, ECC_KEY_LENGTH_521, ECC_KAT_VECTORS_ECDSA_SIGNED,
ECC_KAT_VECTORS_ECDSA_SIGNED_LEN, &signature);
if (status != 0) {
goto exit;
}
if (signature.length != ECC_KEY_LENGTH_521) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE.r, signature.r,
ECC_KEY_LENGTH_521);
if (status != 0) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
goto exit;
}
status = buffer_compare (ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE.s, signature.s,
ECC_KEY_LENGTH_521);
if (status != 0) {
status = ECDSA_P521_SIGN_SELF_TEST_FAILED;
}
exit:
buffer_zeroize (&signature, sizeof (signature));
return status;
#else
UNUSED (ecc_hw);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification directly against an ECC hardware
* driver interface using ECC P-256 and SHA-256.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_verify_p256_sha256 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
int status;
status = ecdsa_ecc_hw_verify_message (ecc_hw, hash, HASH_TYPE_SHA256,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN,
&ECC_KAT_VECTORS_P256_ECC_PUBLIC, &ECC_KAT_VECTORS_P256_SHA256_ECDSA_SIGNATURE);
if (status == ECC_HW_ECDSA_BAD_SIGNATURE) {
status = ECDSA_P256_VERIFY_SELF_TEST_FAILED;
}
return status;
}
/**
* Run an ECDSA known answer test (KAT) for signature verification directly against an ECC hardware
* driver interface using ECC P-384 and SHA-384.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_verify_p384_sha384 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA384) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384)
int status;
status = ecdsa_ecc_hw_verify_message (ecc_hw, hash, HASH_TYPE_SHA384,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN,
&ECC_KAT_VECTORS_P384_ECC_PUBLIC, &ECC_KAT_VECTORS_P384_SHA384_ECDSA_SIGNATURE);
if (status == ECC_HW_ECDSA_BAD_SIGNATURE) {
status = ECDSA_P384_VERIFY_SELF_TEST_FAILED;
}
return status;
#else
UNUSED (ecc_hw);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}
/**
* Run an ECDSA known answer test (KAT) for signature verification directly against an ECC hardware
* driver interface using ECC P-521 and SHA-512.
*
* It's only necessary to run an ECDSA signature verification self-test for a single curve supported
* by the platform.
*
* @param ecc_hw The ECC hardware instance to use for the self-test.
* @param hash The hash engine to use for the self-test.
*
* @return 0 if the self-test completed successfully or an error code.
*/
int ecdsa_kat_run_self_test_ecc_hw_verify_p521_sha512 (const struct ecc_hw *ecc_hw,
const struct hash_engine *hash)
{
#if (defined HASH_ENABLE_SHA512) && (ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521)
int status;
status = ecdsa_ecc_hw_verify_message (ecc_hw, hash, HASH_TYPE_SHA512,
ECC_KAT_VECTORS_ECDSA_SIGNED, ECC_KAT_VECTORS_ECDSA_SIGNED_LEN,
&ECC_KAT_VECTORS_P521_ECC_PUBLIC, &ECC_KAT_VECTORS_P521_SHA512_ECDSA_SIGNATURE);
if (status == ECC_HW_ECDSA_BAD_SIGNATURE) {
status = ECDSA_P521_VERIFY_SELF_TEST_FAILED;
}
return status;
#else
UNUSED (ecc_hw);
UNUSED (hash);
return ECDSA_UNSUPPORTED_SELF_TEST;
#endif
}