mirror of
https://github.com/espressif/openthread.git
synced 2026-08-17 16:09:51 +00:00
[crypto] add ECDSA API (#8273)
- remove ecdsa tinycrypt implementation - add crypto API, move default implementation in crypto_platform.c - define crypto ecdsa structures and format
This commit is contained in:
@@ -255,7 +255,6 @@ LOCAL_SRC_FILES := \
|
||||
src/core/crypto/aes_ecb.cpp \
|
||||
src/core/crypto/crypto_platform.cpp \
|
||||
src/core/crypto/ecdsa.cpp \
|
||||
src/core/crypto/ecdsa_tinycrypt.cpp \
|
||||
src/core/crypto/hkdf_sha256.cpp \
|
||||
src/core/crypto/hmac_sha256.cpp \
|
||||
src/core/crypto/mbedtls.cpp \
|
||||
|
||||
@@ -55,25 +55,13 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_CRYPTO_SHA256_HASH_SIZE 32 ///< Length of SHA256 hash (in bytes).
|
||||
|
||||
/**
|
||||
* @struct otCryptoSha256Hash
|
||||
*
|
||||
* This structure represents a SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct otCryptoSha256Hash
|
||||
{
|
||||
uint8_t m8[OT_CRYPTO_SHA256_HASH_SIZE]; ///< Hash bytes.
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This structure represents a SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
typedef struct otCryptoSha256Hash otCryptoSha256Hash;
|
||||
typedef otPlatCryptoSha256Hash otCryptoSha256Hash;
|
||||
|
||||
/**
|
||||
* This function performs HMAC computation.
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (258)
|
||||
#define OPENTHREAD_API_VERSION (259)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -130,6 +130,95 @@ typedef struct otCryptoContext
|
||||
uint16_t mContextSize; ///< The length of the context in bytes.
|
||||
} otCryptoContext;
|
||||
|
||||
/**
|
||||
* Length of SHA256 hash (in bytes).
|
||||
*
|
||||
*/
|
||||
#define OT_CRYPTO_SHA256_HASH_SIZE 32
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoSha256Hash
|
||||
*
|
||||
* This structure represents a SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct otPlatCryptoSha256Hash
|
||||
{
|
||||
uint8_t m8[OT_CRYPTO_SHA256_HASH_SIZE]; ///< Hash bytes.
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This structure represents a SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
typedef struct otPlatCryptoSha256Hash otPlatCryptoSha256Hash;
|
||||
|
||||
/**
|
||||
* Max buffer size (in bytes) for representing the EDCSA key-pair in DER format.
|
||||
*
|
||||
*/
|
||||
#define OT_CRYPTO_ECDSA_MAX_DER_SIZE 125
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoEcdsaKeyPair
|
||||
*
|
||||
* This structure represents an ECDSA key pair (public and private keys).
|
||||
*
|
||||
* The key pair is stored using Distinguished Encoding Rules (DER) format (per RFC 5915).
|
||||
*
|
||||
*/
|
||||
typedef struct otPlatCryptoEcdsaKeyPair
|
||||
{
|
||||
uint8_t mDerBytes[OT_CRYPTO_ECDSA_MAX_DER_SIZE];
|
||||
uint8_t mDerLength;
|
||||
} otPlatCryptoEcdsaKeyPair;
|
||||
|
||||
/**
|
||||
* Buffer size (in bytes) for representing the EDCSA public key.
|
||||
*
|
||||
*/
|
||||
#define OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE 64
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoEcdsaPublicKey
|
||||
*
|
||||
* This struct represents a ECDSA public key.
|
||||
*
|
||||
* The public key is stored as a byte sequence representation of an uncompressed curve point (RFC 6605 - sec 4).
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct otPlatCryptoEcdsaPublicKey
|
||||
{
|
||||
uint8_t m8[OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
typedef struct otPlatCryptoEcdsaPublicKey otPlatCryptoEcdsaPublicKey;
|
||||
|
||||
/**
|
||||
* Buffer size (in bytes) for representing the EDCSA signature.
|
||||
*
|
||||
*/
|
||||
#define OT_CRYPTO_ECDSA_SIGNATURE_SIZE 64
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoEcdsaSignature
|
||||
*
|
||||
* This struct represents an ECDSA signature.
|
||||
*
|
||||
* The signature is encoded as the concatenated binary representation of two MPIs `r` and `s` which are calculated
|
||||
* during signing (RFC 6605 - section 4).
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct otPlatCryptoEcdsaSignature
|
||||
{
|
||||
uint8_t m8[OT_CRYPTO_ECDSA_SIGNATURE_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
typedef struct otPlatCryptoEcdsaSignature otPlatCryptoEcdsaSignature;
|
||||
|
||||
/**
|
||||
* Initialize the Crypto module.
|
||||
*
|
||||
@@ -480,15 +569,81 @@ void otPlatCryptoRandomDeinit(void);
|
||||
/**
|
||||
* Fills a given buffer with cryptographically secure random bytes.
|
||||
*
|
||||
* @param[out] aBuffer A pointer to a buffer to fill with the random bytes.
|
||||
* @param[in] aSize Size of buffer (number of bytes to fill).
|
||||
* @param[out] aBuffer A pointer to a buffer to fill with the random bytes.
|
||||
* @param[in] aSize Size of buffer (number of bytes to fill).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully filled buffer with random values.
|
||||
* @retval OT_ERROR_FAILED Operation failed.
|
||||
* @retval OT_ERROR_NONE Successfully filled buffer with random values.
|
||||
* @retval OT_ERROR_FAILED Operation failed.
|
||||
*
|
||||
*/
|
||||
otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize);
|
||||
|
||||
/**
|
||||
* Generate and populate the output buffer with a new ECDSA key-pair.
|
||||
*
|
||||
* @param[out] aKeyPair A pointer to an ECDSA key-pair structure to store the generated key-pair.
|
||||
*
|
||||
* @retval OT_ERROR_NONE A new key-pair was generated successfully.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer for key generation.
|
||||
* @retval OT_ERROR_NOT_CAPABLE Feature not supported.
|
||||
* @retval OT_ERROR_FAILED Failed to generate key-pair.
|
||||
*
|
||||
*/
|
||||
otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair);
|
||||
|
||||
/**
|
||||
* Get the associated public key from the input context.
|
||||
*
|
||||
* @param[in] aKeyPair A pointer to an ECDSA key-pair structure where the key-pair is stored.
|
||||
* @param[out] aPublicKey A pointer to an ECDSA public key structure to store the public key.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Public key was retrieved successfully, and @p aBuffer is updated.
|
||||
* @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format).
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aContext is NULL.
|
||||
*
|
||||
*/
|
||||
otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair, otPlatCryptoEcdsaPublicKey *aPublicKey);
|
||||
|
||||
/**
|
||||
* Calculate the ECDSA signature for a hashed message using the private key from the input context.
|
||||
*
|
||||
* This method uses the deterministic digital signature generation procedure from RFC 6979.
|
||||
*
|
||||
* @param[in] aKeyPair A pointer to an ECDSA key-pair structure where the key-pair is stored.
|
||||
* @param[in] aHash A pointer to a SHA-256 hash structure where the hash value for signature calculation
|
||||
* is stored.
|
||||
* @param[out] aSignature A pointer to an ECDSA signature structure to output the calculated signature.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The signature was calculated successfully, @p aSignature was updated.
|
||||
* @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format).
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature calculation.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aContext is NULL.
|
||||
*
|
||||
*/
|
||||
otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair,
|
||||
const otPlatCryptoSha256Hash * aHash,
|
||||
otPlatCryptoEcdsaSignature * aSignature);
|
||||
|
||||
/**
|
||||
* Use the key from the input context to verify the ECDSA signature of a hashed message.
|
||||
*
|
||||
* @param[in] aPublicKey A pointer to an ECDSA public key structure where the public key for signature
|
||||
* verification is stored.
|
||||
* @param[in] aHash A pointer to a SHA-256 hash structure where the hash value for signature verification
|
||||
* is stored.
|
||||
* @param[in] aSignature A pointer to an ECDSA signature structure where the signature value to be verified is
|
||||
* stored.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The signature was verified successfully.
|
||||
* @retval OT_ERROR_SECURITY The signature is invalid.
|
||||
* @retval OT_ERROR_INVALID_ARGS The key or hash is invalid.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature verification.
|
||||
*
|
||||
*/
|
||||
otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey,
|
||||
const otPlatCryptoSha256Hash * aHash,
|
||||
const otPlatCryptoEcdsaSignature *aSignature);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -463,7 +463,6 @@ openthread_core_files = [
|
||||
"crypto/crypto_platform.cpp",
|
||||
"crypto/ecdsa.cpp",
|
||||
"crypto/ecdsa.hpp",
|
||||
"crypto/ecdsa_tinycrypt.cpp",
|
||||
"crypto/hkdf_sha256.cpp",
|
||||
"crypto/hkdf_sha256.hpp",
|
||||
"crypto/hmac_sha256.cpp",
|
||||
|
||||
@@ -121,7 +121,6 @@ set(COMMON_SOURCES
|
||||
crypto/aes_ecb.cpp
|
||||
crypto/crypto_platform.cpp
|
||||
crypto/ecdsa.cpp
|
||||
crypto/ecdsa_tinycrypt.cpp
|
||||
crypto/hkdf_sha256.cpp
|
||||
crypto/hmac_sha256.cpp
|
||||
crypto/mbedtls.cpp
|
||||
|
||||
@@ -211,7 +211,6 @@ SOURCES_COMMON = \
|
||||
crypto/aes_ecb.cpp \
|
||||
crypto/crypto_platform.cpp \
|
||||
crypto/ecdsa.cpp \
|
||||
crypto/ecdsa_tinycrypt.cpp \
|
||||
crypto/hkdf_sha256.cpp \
|
||||
crypto/hmac_sha256.cpp \
|
||||
crypto/mbedtls.cpp \
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/pk.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/version.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/platform/crypto.h>
|
||||
@@ -48,6 +51,7 @@
|
||||
#include "common/instance.hpp"
|
||||
#include "common/new.hpp"
|
||||
#include "config/crypto.h"
|
||||
#include "crypto/ecdsa.hpp"
|
||||
#include "crypto/hmac_sha256.hpp"
|
||||
#include "crypto/storage.hpp"
|
||||
|
||||
@@ -484,6 +488,175 @@ OT_TOOL_WEAK otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize)
|
||||
mbedtls_ctr_drbg_random(&sCtrDrbgContext, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair)
|
||||
{
|
||||
mbedtls_pk_context pk;
|
||||
int ret;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
|
||||
VerifyOrExit(ret == 0);
|
||||
|
||||
ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(pk), MbedTls::CryptoSecurePrng, nullptr);
|
||||
VerifyOrExit(ret == 0);
|
||||
|
||||
ret = mbedtls_pk_write_key_der(&pk, aKeyPair->mDerBytes, OT_CRYPTO_ECDSA_MAX_DER_SIZE);
|
||||
VerifyOrExit(ret > 0);
|
||||
|
||||
aKeyPair->mDerLength = static_cast<uint8_t>(ret);
|
||||
|
||||
memmove(aKeyPair->mDerBytes, aKeyPair->mDerBytes + OT_CRYPTO_ECDSA_MAX_DER_SIZE - aKeyPair->mDerLength,
|
||||
aKeyPair->mDerLength);
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
return (ret >= 0) ? kErrorNone : MbedTls::MapError(ret);
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair,
|
||||
otPlatCryptoEcdsaPublicKey * aPublicKey)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_ecp_keypair *keyPair;
|
||||
int ret;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
VerifyOrExit(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pk, aKeyPair->mDerBytes, aKeyPair->mDerLength, nullptr, 0,
|
||||
MbedTls::CryptoSecurePrng, nullptr) == 0,
|
||||
error = kErrorParse);
|
||||
#else
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pk, aKeyPair->mDerBytes, aKeyPair->mDerLength, nullptr, 0) == 0,
|
||||
error = kErrorParse);
|
||||
#endif
|
||||
|
||||
keyPair = mbedtls_pk_ec(pk);
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&keyPair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), aPublicKey->m8,
|
||||
Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&keyPair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
|
||||
aPublicKey->m8 + Ecdsa::P256::kMpiSize, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
return error;
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair,
|
||||
const otPlatCryptoSha256Hash * aHash,
|
||||
otPlatCryptoEcdsaSignature * aSignature)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_ecp_keypair * keypair;
|
||||
mbedtls_ecdsa_context ecdsa;
|
||||
mbedtls_mpi r;
|
||||
mbedtls_mpi s;
|
||||
int ret;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
mbedtls_ecdsa_init(&ecdsa);
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
VerifyOrExit(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pk, aKeyPair->mDerBytes, aKeyPair->mDerLength, nullptr, 0,
|
||||
MbedTls::CryptoSecurePrng, nullptr) == 0,
|
||||
error = kErrorParse);
|
||||
#else
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pk, aKeyPair->mDerBytes, aKeyPair->mDerLength, nullptr, 0) == 0,
|
||||
error = kErrorParse);
|
||||
#endif
|
||||
|
||||
keypair = mbedtls_pk_ec(pk);
|
||||
|
||||
ret = mbedtls_ecdsa_from_keypair(&ecdsa, keypair);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x02130000)
|
||||
ret = mbedtls_ecdsa_sign_det_ext(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash->m8,
|
||||
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->m8,
|
||||
Sha256::Hash::kSize, MBEDTLS_MD_SHA256);
|
||||
#endif
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
OT_ASSERT(mbedtls_mpi_size(&r) <= Ecdsa::P256::kMpiSize);
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&r, aSignature->m8, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&s, aSignature->m8 + Ecdsa::P256::kMpiSize, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey,
|
||||
const otPlatCryptoSha256Hash * aHash,
|
||||
const otPlatCryptoEcdsaSignature *aSignature)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_ecdsa_context ecdsa;
|
||||
mbedtls_mpi r;
|
||||
mbedtls_mpi s;
|
||||
int ret;
|
||||
|
||||
mbedtls_ecdsa_init(&ecdsa);
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
ret = mbedtls_ecp_group_load(&ecdsa.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), aPublicKey->m8, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
ret = mbedtls_mpi_read_binary(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), aPublicKey->m8 + Ecdsa::P256::kMpiSize,
|
||||
Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
ret = mbedtls_mpi_lset(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&r, aSignature->m8, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&s, aSignature->m8 + Ecdsa::P256::kMpiSize, Ecdsa::P256::kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_ecdsa_verify(&ecdsa.MBEDTLS_PRIVATE(grp), aHash->m8, Sha256::Hash::kSize, &ecdsa.MBEDTLS_PRIVATE(Q),
|
||||
&r, &s);
|
||||
VerifyOrExit(ret == 0, error = kErrorSecurity);
|
||||
|
||||
exit:
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
#endif // #if !OPENTHREAD_RADIO
|
||||
|
||||
#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
|
||||
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
#ifndef MBEDTLS_USE_TINYCRYPT
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
@@ -53,166 +51,6 @@ namespace ot {
|
||||
namespace Crypto {
|
||||
namespace Ecdsa {
|
||||
|
||||
Error P256::KeyPair::Generate(void)
|
||||
{
|
||||
mbedtls_pk_context pk;
|
||||
int ret;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
|
||||
VerifyOrExit(ret == 0);
|
||||
|
||||
ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(pk), MbedTls::CryptoSecurePrng, nullptr);
|
||||
VerifyOrExit(ret == 0);
|
||||
|
||||
ret = mbedtls_pk_write_key_der(&pk, mDerBytes, sizeof(mDerBytes));
|
||||
VerifyOrExit(ret > 0);
|
||||
|
||||
mDerLength = static_cast<uint8_t>(ret);
|
||||
|
||||
memmove(mDerBytes, mDerBytes + sizeof(mDerBytes) - mDerLength, mDerLength);
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
return (ret >= 0) ? kErrorNone : MbedTls::MapError(ret);
|
||||
}
|
||||
|
||||
Error P256::KeyPair::Parse(void *aContext) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_pk_context *pk = reinterpret_cast<mbedtls_pk_context *>(aContext);
|
||||
|
||||
mbedtls_pk_init(pk);
|
||||
|
||||
VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0, MbedTls::CryptoSecurePrng, nullptr) == 0,
|
||||
error = kErrorParse);
|
||||
#else
|
||||
VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = kErrorParse);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const
|
||||
{
|
||||
Error error;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_ecp_keypair *keyPair;
|
||||
int ret;
|
||||
|
||||
SuccessOrExit(error = Parse(&pk));
|
||||
|
||||
keyPair = mbedtls_pk_ec(pk);
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&keyPair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), aPublicKey.mData, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&keyPair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), aPublicKey.mData + kMpiSize,
|
||||
kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) const
|
||||
{
|
||||
Error error;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_ecp_keypair * keypair;
|
||||
mbedtls_ecdsa_context ecdsa;
|
||||
mbedtls_mpi r;
|
||||
mbedtls_mpi s;
|
||||
int ret;
|
||||
|
||||
mbedtls_ecdsa_init(&ecdsa);
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
SuccessOrExit(error = Parse(&pk));
|
||||
|
||||
keypair = mbedtls_pk_ec(pk);
|
||||
|
||||
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));
|
||||
|
||||
OT_ASSERT(mbedtls_mpi_size(&r) <= kMpiSize);
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&r, aSignature.mShared.mMpis.mR, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_write_binary(&s, aSignature.mShared.mMpis.mS, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_ecdsa_context ecdsa;
|
||||
mbedtls_mpi r;
|
||||
mbedtls_mpi s;
|
||||
int ret;
|
||||
|
||||
mbedtls_ecdsa_init(&ecdsa);
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
ret = mbedtls_ecp_group_load(&ecdsa.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), GetBytes(), kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
ret = mbedtls_mpi_read_binary(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), GetBytes() + kMpiSize, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
ret = mbedtls_mpi_lset(&ecdsa.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&r, aSignature.mShared.mMpis.mR, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&s, aSignature.mShared.mMpis.mS, kMpiSize);
|
||||
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
|
||||
|
||||
ret = mbedtls_ecdsa_verify(&ecdsa.MBEDTLS_PRIVATE(grp), aHash.GetBytes(), Sha256::Hash::kSize,
|
||||
&ecdsa.MBEDTLS_PRIVATE(Q), &r, &s);
|
||||
VerifyOrExit(ret == 0, error = kErrorSecurity);
|
||||
|
||||
exit:
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Sign(uint8_t * aOutput,
|
||||
uint16_t & aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
@@ -286,5 +124,4 @@ exit:
|
||||
} // namespace Crypto
|
||||
} // namespace ot
|
||||
|
||||
#endif // MBEDTLS_USE_TINYCRYPT
|
||||
#endif // OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
+27
-39
@@ -41,6 +41,9 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openthread/crypto.h>
|
||||
#include <openthread/platform/crypto.h>
|
||||
|
||||
#include "common/error.hpp"
|
||||
#include "crypto/sha256.hpp"
|
||||
|
||||
@@ -83,13 +86,13 @@ public:
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class Signature
|
||||
class Signature : public otPlatCryptoEcdsaSignature
|
||||
{
|
||||
friend class KeyPair;
|
||||
friend class PublicKey;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kSize = 2 * kMpiSize; ///< Signature size in bytes (two times the curve MPI size).
|
||||
static constexpr uint8_t kSize = OT_CRYPTO_ECDSA_SIGNATURE_SIZE; ///< Signature size in bytes.
|
||||
|
||||
/**
|
||||
* This method returns the signature as a byte array.
|
||||
@@ -97,21 +100,7 @@ public:
|
||||
* @returns A pointer to the byte array containing the signature.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetBytes(void) const { return mShared.mKey; }
|
||||
|
||||
private:
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct Mpis
|
||||
{
|
||||
uint8_t mR[kMpiSize];
|
||||
uint8_t mS[kMpiSize];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
union OT_TOOL_PACKED_FIELD
|
||||
{
|
||||
Mpis mMpis;
|
||||
uint8_t mKey[kSize];
|
||||
} mShared;
|
||||
const uint8_t *GetBytes(void) const { return m8; }
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
@@ -120,23 +109,20 @@ public:
|
||||
* The key pair is stored using Distinguished Encoding Rules (DER) format (per RFC 5915).
|
||||
*
|
||||
*/
|
||||
class KeyPair
|
||||
class KeyPair : public otPlatCryptoEcdsaKeyPair
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Max buffer size (in bytes) for representing the key-pair in DER format.
|
||||
*
|
||||
*/
|
||||
static constexpr uint8_t kMaxDerSize = 125;
|
||||
static constexpr uint8_t kMaxDerSize = OT_CRYPTO_ECDSA_MAX_DER_SIZE;
|
||||
|
||||
/**
|
||||
* This constructor initializes a `KeyPair` as empty (no key).
|
||||
*
|
||||
*/
|
||||
KeyPair(void)
|
||||
: mDerLength(0)
|
||||
{
|
||||
}
|
||||
KeyPair(void) { mDerLength = 0; }
|
||||
|
||||
/**
|
||||
* This method generates and populates the `KeyPair` with a new public/private keys.
|
||||
@@ -147,7 +133,7 @@ public:
|
||||
* @retval kErrorFailed Failed to generate key.
|
||||
*
|
||||
*/
|
||||
Error Generate(void);
|
||||
Error Generate(void) { return otPlatCryptoEcdsaGenerateKey(this); }
|
||||
|
||||
/**
|
||||
* This method gets the associated public key from the `KeyPair`.
|
||||
@@ -158,7 +144,7 @@ public:
|
||||
* @retval kErrorParse The key-pair DER format could not be parsed (invalid format).
|
||||
*
|
||||
*/
|
||||
Error GetPublicKey(PublicKey &aPublicKey) const;
|
||||
Error GetPublicKey(PublicKey &aPublicKey) const { return otPlatCryptoEcdsaGetPublicKey(this, &aPublicKey); }
|
||||
|
||||
/**
|
||||
* This method gets the pointer to start of the buffer containing the key-pair info in DER format.
|
||||
@@ -212,13 +198,10 @@ public:
|
||||
* @retval kErrorNoBufs Failed to allocate buffer for signature calculation.
|
||||
*
|
||||
*/
|
||||
Error Sign(const Sha256::Hash &aHash, Signature &aSignature) const;
|
||||
|
||||
private:
|
||||
Error Parse(void *aContext) const;
|
||||
|
||||
uint8_t mDerBytes[kMaxDerSize];
|
||||
uint8_t mDerLength;
|
||||
Error Sign(const Sha256::Hash &aHash, Signature &aSignature) const
|
||||
{
|
||||
return otPlatCryptoEcdsaSign(this, &aHash, &aSignature);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -228,12 +211,12 @@ public:
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class PublicKey : public Equatable<PublicKey>
|
||||
class PublicKey : public otPlatCryptoEcdsaPublicKey, public Equatable<PublicKey>
|
||||
{
|
||||
friend class KeyPair;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kSize = kMpiSize * 2; ///< Size of the public key in bytes.
|
||||
static constexpr uint8_t kSize = OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE; ///< Size of the public key in bytes.
|
||||
|
||||
/**
|
||||
* This method gets the pointer to the buffer containing the public key (as an uncompressed curve point).
|
||||
@@ -241,7 +224,7 @@ public:
|
||||
* @return The pointer to the buffer containing the public key (with `kSize` bytes).
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetBytes(void) const { return mData; }
|
||||
const uint8_t *GetBytes(void) const { return m8; }
|
||||
|
||||
/**
|
||||
* This method uses the `PublicKey` to verify the ECDSA signature of a hashed message.
|
||||
@@ -255,10 +238,10 @@ public:
|
||||
* @retval kErrorNoBufs Failed to allocate buffer for signature verification
|
||||
*
|
||||
*/
|
||||
Error Verify(const Sha256::Hash &aHash, const Signature &aSignature) const;
|
||||
|
||||
private:
|
||||
uint8_t mData[kSize];
|
||||
Error Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
|
||||
{
|
||||
return otPlatCryptoEcdsaVerify(this, &aHash, &aSignature);
|
||||
}
|
||||
} OT_TOOL_PACKED_END;
|
||||
};
|
||||
|
||||
@@ -292,6 +275,11 @@ Error Sign(uint8_t * aOutput,
|
||||
|
||||
} // namespace Ecdsa
|
||||
} // namespace Crypto
|
||||
|
||||
DefineCoreType(otPlatCryptoEcdsaSignature, Crypto::Ecdsa::P256::Signature);
|
||||
DefineCoreType(otPlatCryptoEcdsaKeyPair, Crypto::Ecdsa::P256::KeyPair);
|
||||
DefineCoreType(otPlatCryptoEcdsaPublicKey, Crypto::Ecdsa::P256::PublicKey);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements ECDSA signing using TinyCrypt library.
|
||||
*/
|
||||
|
||||
#include "ecdsa.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
|
||||
#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>
|
||||
#include <mbedtls/version.h>
|
||||
|
||||
#include <tinycrypt/ecc.h>
|
||||
#include <tinycrypt/ecc_dh.h>
|
||||
#include <tinycrypt/ecc_dsa.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "crypto/mbedtls.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Crypto {
|
||||
namespace Ecdsa {
|
||||
|
||||
Error P256::KeyPair::Generate(void)
|
||||
{
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_uecc_keypair *keypair;
|
||||
int ret;
|
||||
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
|
||||
VerifyOrExit(ret == 0);
|
||||
|
||||
keypair = mbedtls_pk_uecc(pk);
|
||||
|
||||
ret = uECC_make_key(keypair->public_key, keypair->private_key);
|
||||
VerifyOrExit(ret == UECC_SUCCESS);
|
||||
|
||||
ret = mbedtls_pk_write_key_der(&pk, mDerBytes, sizeof(mDerBytes));
|
||||
VerifyOrExit(ret > 0);
|
||||
|
||||
mDerLength = static_cast<uint8_t>(ret);
|
||||
|
||||
memmove(mDerBytes, mDerBytes + sizeof(mDerBytes) - mDerLength, mDerLength);
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
return (ret >= 0) ? kErrorNone : MbedTls::MapError(ret);
|
||||
}
|
||||
|
||||
Error P256::KeyPair::Parse(void *aContext) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_pk_context *pk = reinterpret_cast<mbedtls_pk_context *>(aContext);
|
||||
|
||||
mbedtls_pk_init(pk);
|
||||
|
||||
VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0, MbedTls::CryptoSecurePrng, nullptr) == 0,
|
||||
error = kErrorParse);
|
||||
#else
|
||||
VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = kErrorParse);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const
|
||||
{
|
||||
Error error;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_uecc_keypair *keyPair;
|
||||
int ret;
|
||||
|
||||
SuccessOrExit(error = Parse(&pk));
|
||||
|
||||
keyPair = mbedtls_pk_uecc(pk);
|
||||
|
||||
memcpy(aPublicKey.mData, keyPair->public_key, kMpiSize);
|
||||
memcpy(aPublicKey.mData + kMpiSize, keyPair->public_key + kMpiSize, kMpiSize);
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) const
|
||||
{
|
||||
Error error;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_uecc_keypair *keypair;
|
||||
int ret;
|
||||
uint8_t sig[2 * kMpiSize];
|
||||
|
||||
SuccessOrExit(error = Parse(&pk));
|
||||
|
||||
keypair = mbedtls_pk_uecc(pk);
|
||||
|
||||
ret = uECC_sign(keypair->private_key, aHash.GetBytes(), Sha256::Hash::kSize, sig);
|
||||
VerifyOrExit(ret == UECC_SUCCESS, error = MbedTls::MapError(ret));
|
||||
|
||||
memcpy(aSignature.mShared.mMpis.mR, sig, kMpiSize);
|
||||
memcpy(aSignature.mShared.mMpis.mS, sig + kMpiSize, kMpiSize);
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
int ret;
|
||||
uint8_t public_key[2 * kMpiSize];
|
||||
uint8_t sig[2 * kMpiSize];
|
||||
|
||||
memcpy(public_key, GetBytes(), 2 * kMpiSize);
|
||||
|
||||
memcpy(sig, aSignature.mShared.mMpis.mR, kMpiSize);
|
||||
memcpy(sig + kMpiSize, aSignature.mShared.mMpis.mS, kMpiSize);
|
||||
|
||||
ret = uECC_verify(public_key, aHash.GetBytes(), Sha256::Hash::kSize, sig);
|
||||
VerifyOrExit(ret == UECC_SUCCESS, error = kErrorSecurity);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Sign(uint8_t * aOutput,
|
||||
uint16_t & aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
uint16_t aInputHashLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint16_t aPrivateKeyLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_pk_context pkCtx;
|
||||
mbedtls_uecc_keypair *keypair;
|
||||
uint8_t sig[2 * NUM_ECC_BYTES];
|
||||
|
||||
mbedtls_pk_init(&pkCtx);
|
||||
|
||||
// Parse a private key in PEM format.
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0) == 0,
|
||||
error = kErrorInvalidArgs);
|
||||
VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = kErrorInvalidArgs);
|
||||
|
||||
keypair = mbedtls_pk_uecc(pkCtx);
|
||||
OT_ASSERT(keypair != nullptr);
|
||||
|
||||
// Sign using ECDSA.
|
||||
VerifyOrExit(uECC_sign(keypair->private_key, aInputHash, aInputHashLength, sig) == UECC_SUCCESS,
|
||||
error = kErrorFailed);
|
||||
VerifyOrExit(2 * NUM_ECC_BYTES <= aOutputLength, error = kErrorNoBufs);
|
||||
|
||||
// Concatenate the two octet sequences in the order R and then S.
|
||||
memcpy(aOutput, sig, 2 * NUM_ECC_BYTES);
|
||||
aOutputLength = 2 * NUM_ECC_BYTES;
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free(&pkCtx);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Ecdsa
|
||||
} // namespace Crypto
|
||||
} // namespace ot
|
||||
|
||||
#endif // MBEDTLS_USE_TINYCRYPT
|
||||
#endif // OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
Reference in New Issue
Block a user