[crypto] allow selecting randomized ECDSA instead of deterministic (#7894)

There is no hard dependency in the Thread specification which requires
the use of deterministic signatures. On the contrary, looking at the
tinycrypt implementation, that one issues randomized ECDSA signatures
and seems to be quite happy with that.

This change does not change the default behaviour, which is to use
deterministic ECDSA when using the default MbedTLS backend. It does
however make it possible for platforms which have qualified hardware
entropy to select 'plain' ECDSA instead, which gives both a performance
and code size improvement on those platforms.
This commit is contained in:
Steven Cooreman
2022-08-08 19:27:12 +02:00
committed by GitHub
parent cbbed06931
commit 0b41ae0a30
6 changed files with 50 additions and 2 deletions
@@ -254,4 +254,15 @@
#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES 20
#endif
/**
* @def OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
*
* Define to 1 to generate ECDSA signatures determinsitically
* according to RFC 6979 instead of randomly.
*
*/
#ifndef OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#define OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE 1
#endif
#endif // OPENTHREAD_CORE_SIMULATION_CONFIG_H_
+11
View File
@@ -87,6 +87,17 @@
#define OPENTHREAD_CONFIG_ECDSA_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
*
* Define to 1 to generate ECDSA signatures determinsitically
* according to RFC 6979 instead of randomly.
*
*/
#ifndef OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#define OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE 1
#endif
/**
* @def OPENTHREAD_CONFIG_UPTIME_ENABLE
*
+16
View File
@@ -142,12 +142,17 @@ Error P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) cons
ret = mbedtls_ecdsa_from_keypair(&ecdsa, keypair);
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#if (MBEDTLS_VERSION_NUMBER >= 0x02130000)
ret = mbedtls_ecdsa_sign_det_ext(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash.GetBytes(),
Sha256::Hash::kSize, MBEDTLS_MD_SHA256, MbedTls::CryptoSecurePrng, nullptr);
#else
ret = mbedtls_ecdsa_sign_det(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash.GetBytes(),
Sha256::Hash::kSize, MBEDTLS_MD_SHA256);
#endif
#else
ret = mbedtls_ecdsa_sign(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash.GetBytes(),
Sha256::Hash::kSize, MbedTls::CryptoSecurePrng, nullptr);
#endif
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
@@ -244,9 +249,20 @@ Error Sign(uint8_t * aOutput,
VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = kErrorFailed);
// Sign using ECDSA.
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#if (MBEDTLS_VERSION_NUMBER >= 0x02130000)
VerifyOrExit(mbedtls_ecdsa_sign_det_ext(&ctx.MBEDTLS_PRIVATE(grp), &rMpi, &sMpi, &ctx.MBEDTLS_PRIVATE(d),
aInputHash, aInputHashLength, MBEDTLS_MD_SHA256, MbedTls::CryptoSecurePrng,
nullptr));
#else
VerifyOrExit(mbedtls_ecdsa_sign_det(&ctx.MBEDTLS_PRIVATE(grp), &rMpi, &sMpi, &ctx.MBEDTLS_PRIVATE(d), aInputHash,
aInputHashLength, MBEDTLS_MD_SHA256));
#endif
#else
VerifyOrExit(mbedtls_ecdsa_sign(&ctx.MBEDTLS_PRIVATE(grp), &rMpi, &sMpi, &ctx.MBEDTLS_PRIVATE(d), aInputHash,
aInputHashLength, MbedTls::CryptoSecurePrng, nullptr) == 0,
error = kErrorFailed);
#endif
VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= aOutputLength, error = kErrorNoBufs);
// Concatenate the two octet sequences in the order R and then S.
+4
View File
@@ -37,6 +37,10 @@
#ifdef MBEDTLS_USE_TINYCRYPT
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#warning "tinycrypt does not support generating deterministic ECDSA signatures"
#endif
#include <string.h>
#include <mbedtls/pk.h>
+6 -2
View File
@@ -66,12 +66,14 @@ void TestEcdsaVector(void)
const uint8_t kMessage[] = {'s', 'a', 'm', 'p', 'l', 'e'};
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
const uint8_t kExpectedSignature[] = {
0xEF, 0xD4, 0x8B, 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40, 0xDD, 0x9C, 0xD4, 0x5E, 0x81, 0xD6,
0x9D, 0x2C, 0x87, 0x7B, 0x56, 0xAA, 0xF9, 0x91, 0xC3, 0x4D, 0x0E, 0xA8, 0x4E, 0xAF, 0x37, 0x16,
0xF7, 0xCB, 0x1C, 0x94, 0x2D, 0x65, 0x7C, 0x41, 0xD4, 0x36, 0xC7, 0xA1, 0xB6, 0xE2, 0x9F, 0x65,
0xF3, 0xE9, 0x00, 0xDB, 0xB9, 0xAF, 0xF4, 0x06, 0x4D, 0xC4, 0xAB, 0x2F, 0x84, 0x3A, 0xCD, 0xA8,
};
#endif
Instance *instance = testInitInstance();
@@ -110,6 +112,7 @@ void TestEcdsaVector(void)
SuccessOrQuit(keyPair.Sign(hash, signature));
DumpBuffer("Signature", signature.GetBytes(), sizeof(signature));
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
printf("\nCheck signature against expected sequence----------------------------------\n");
DumpBuffer("Expected signature", kExpectedSignature, sizeof(kExpectedSignature));
@@ -117,6 +120,7 @@ void TestEcdsaVector(void)
VerifyOrQuit(memcmp(signature.GetBytes(), kExpectedSignature, sizeof(kExpectedSignature)) == 0);
printf("Signature matches expected sequence.\n");
#endif
printf("\nVerify the signature ------------------------------------------------------\n");
SuccessOrQuit(publicKey.Verify(hash, signature));
@@ -125,7 +129,7 @@ void TestEcdsaVector(void)
testFreeInstance(instance);
}
void TestEdsaKeyGenerationSignAndVerify(void)
void TestEcdsaKeyGenerationSignAndVerify(void)
{
Instance *instance = testInitInstance();
@@ -183,7 +187,7 @@ int main(void)
{
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
ot::Crypto::TestEcdsaVector();
ot::Crypto::TestEdsaKeyGenerationSignAndVerify();
ot::Crypto::TestEcdsaKeyGenerationSignAndVerify();
printf("All tests passed\n");
#else
printf("ECDSA feature is not enabled\n");
+2
View File
@@ -103,7 +103,9 @@
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE
#define MBEDTLS_ECDSA_DETERMINISTIC
#endif
#define MBEDTLS_OID_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PK_WRITE_C