mirror of
https://github.com/espressif/openthread.git
synced 2026-08-14 22:57:46 +00:00
[crypto] add support for ECDSA signing (#3218)
This commit is contained in:
committed by
Jonathan Hui
parent
e99ce0cf1f
commit
014514442d
+4
-3
@@ -62,6 +62,7 @@ python --version || die
|
||||
--enable-dhcp6-server \
|
||||
--enable-diag \
|
||||
--enable-dns-client \
|
||||
--enable-ecdsa \
|
||||
--enable-ftd \
|
||||
--enable-jam-detection \
|
||||
--enable-joiner \
|
||||
@@ -117,7 +118,7 @@ python --version || die
|
||||
git checkout -- . || die
|
||||
git clean -xfd || die
|
||||
./bootstrap || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 FULL_LOGS=1 JOINER=1 LINK_RAW=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 ECDSA=1 FULL_LOGS=1 JOINER=1 LINK_RAW=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-ftd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-mtd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-ncp-ftd || die
|
||||
@@ -195,7 +196,7 @@ python --version || die
|
||||
git checkout -- . || die
|
||||
git clean -xfd || die
|
||||
./bootstrap || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 FULL_LOGS=1 JOINER=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 ECDSA=1 FULL_LOGS=1 JOINER=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-ftd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-mtd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-ncp-ftd || die
|
||||
@@ -273,7 +274,7 @@ python --version || die
|
||||
git checkout -- . || die
|
||||
git clean -xfd || die
|
||||
./bootstrap || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 FULL_LOGS=1 JOINER=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
BORDER_ROUTER=1 COAP=1 COMMISSIONER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 DNS_CLIENT=1 ECDSA=1 FULL_LOGS=1 JOINER=1 MAC_FILTER=1 MTD_NETDIAG=1 SERVICE=1 UDP_PROXY=1 make -f examples/Makefile-nrf52840 || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-ftd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-cli-mtd || die
|
||||
arm-none-eabi-size output/nrf52840/bin/ot-ncp-ftd || die
|
||||
|
||||
@@ -1498,6 +1498,39 @@ AC_ARG_WITH(
|
||||
AC_SUBST(OPENTHREAD_CUSTOM_LINKER_FILE)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_CUSTOM_LINKER_FILE], [test "${with_custom_linker_file}" = "yes"])
|
||||
|
||||
#
|
||||
# Support for ECDSA
|
||||
#
|
||||
|
||||
AC_MSG_CHECKING([whether to build with ECDSA support])
|
||||
AC_ARG_ENABLE(ecdsa,
|
||||
[AS_HELP_STRING([--enable-ecdsa], [Enable ECDSA support @<:@default=no@:>@.])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
|
||||
no|yes)
|
||||
enable_ecdsa=${enableval}
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value ${enable_ecdsa} for --enable-ecdsa])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enable_ecdsa=no])
|
||||
|
||||
if test "$enable_ecdsa" = "yes"; then
|
||||
OPENTHREAD_ENABLE_ECDSA=1
|
||||
else
|
||||
OPENTHREAD_ENABLE_ECDSA=0
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT(${enable_ecdsa})
|
||||
AC_SUBST(OPENTHREAD_ENABLE_ECDSA)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_ECDSA], [test "${enable_ecdsa}" = "yes"])
|
||||
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_ECDSA], [${OPENTHREAD_ENABLE_ECDSA}], [Define to 1 if you want to enable ECDSA support])
|
||||
|
||||
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
@@ -1888,6 +1921,7 @@ AC_MSG_NOTICE([
|
||||
OpenThread Border Agent support : ${enable_border_agent}
|
||||
OpenThread Border Router support : ${enable_border_router}
|
||||
OpenThread Service support : ${enable_service}
|
||||
OpenThread ECDSA support : ${enable_ecdsa}
|
||||
OpenThread Examples : ${with_examples}
|
||||
OpenThread POSIX Application : ${enable_posix_app}
|
||||
|
||||
|
||||
@@ -87,6 +87,10 @@ ifeq ($(DNS_CLIENT),1)
|
||||
configure_OPTIONS += --enable-dns-client
|
||||
endif
|
||||
|
||||
ifeq ($(ECDSA),1)
|
||||
configure_OPTIONS += --enable-ecdsa
|
||||
endif
|
||||
|
||||
ifeq ($(JAM_DETECTION),1)
|
||||
configure_OPTIONS += --enable-jam-detection
|
||||
endif
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -103,6 +105,28 @@ void otCryptoAesCcm(const uint8_t *aKey,
|
||||
bool aEncrypt,
|
||||
void * aTag);
|
||||
|
||||
/**
|
||||
* This method creates ECDSA sign.
|
||||
*
|
||||
* @param[out] aOutput An output buffer where ECDSA sign should be stored.
|
||||
* @param[inout] aOutputLength The length of the @p aOutput buffer.
|
||||
* @param[in] aInputHash An input hash.
|
||||
* @param[in] aInputHashLength The length of the @p aClaims buffer.
|
||||
* @param[in] aPrivateKey A private key in PEM format.
|
||||
* @param[in] aPrivateKeyLength The length of the @p aPrivateKey buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE ECDSA sign has been created successfully.
|
||||
* @retval OT_ERROR_NO_BUFS Output buffer is too small.
|
||||
* @retval OT_ERROR_INVALID_ARGS Private key is not valid EC Private Key.
|
||||
* @rerval OT_ERROR_FAILED Error during signing.
|
||||
*/
|
||||
otError otCryptoEcdsaSign(uint8_t * aOutput,
|
||||
uint16_t * aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
uint16_t aInputHashLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint16_t aPrivateKeyLength);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -147,6 +147,7 @@ SOURCES_COMMON = \
|
||||
common/trickle_timer.cpp \
|
||||
crypto/aes_ccm.cpp \
|
||||
crypto/aes_ecb.cpp \
|
||||
crypto/ecdsa.cpp \
|
||||
crypto/hmac_sha256.cpp \
|
||||
crypto/mbedtls.cpp \
|
||||
crypto/pbkdf2_cmac.cpp \
|
||||
@@ -304,6 +305,7 @@ HEADERS_COMMON = \
|
||||
common/trickle_timer.hpp \
|
||||
crypto/aes_ccm.hpp \
|
||||
crypto/aes_ecb.hpp \
|
||||
crypto/ecdsa.hpp \
|
||||
crypto/hmac_sha256.hpp \
|
||||
crypto/mbedtls.hpp \
|
||||
crypto/pbkdf2_cmac.h \
|
||||
|
||||
@@ -33,10 +33,12 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
#include <openthread/crypto.h>
|
||||
#include <openthread/error.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "crypto/aes_ccm.hpp"
|
||||
#include "crypto/ecdsa.hpp"
|
||||
#include "crypto/hmac_sha256.hpp"
|
||||
|
||||
using namespace ot::Crypto;
|
||||
@@ -91,3 +93,17 @@ void otCryptoAesCcm(const uint8_t *aKey,
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_ECDSA
|
||||
|
||||
otError otCryptoEcdsaSign(uint8_t * aOutput,
|
||||
uint16_t * aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
uint16_t aInputHashLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint16_t aPrivateKeyLength)
|
||||
{
|
||||
return Ecdsa::Sign(aOutput, aOutputLength, aInputHash, aInputHashLength, aPrivateKey, aPrivateKeyLength);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_ENABLE_ECDSA
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
#include "ecdsa.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <mbedtls/ecdsa.h>
|
||||
#include <mbedtls/pk.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/random.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Crypto {
|
||||
|
||||
#if OPENTHREAD_ENABLE_ECDSA
|
||||
|
||||
otError Ecdsa::Sign(uint8_t * aOutput,
|
||||
uint16_t * aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
uint16_t aInputHashLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint16_t aPrivateKeyLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
mbedtls_ecdsa_context ctx;
|
||||
mbedtls_pk_context pkCtx;
|
||||
mbedtls_ecp_keypair * keypair;
|
||||
mbedtls_mpi rMpi;
|
||||
mbedtls_mpi sMpi;
|
||||
|
||||
mbedtls_pk_init(&pkCtx);
|
||||
mbedtls_ecdsa_init(&ctx);
|
||||
|
||||
// Parse a private key in PEM format.
|
||||
VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, NULL, 0) == 0,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
keypair = mbedtls_pk_ec(pkCtx);
|
||||
assert(keypair != NULL);
|
||||
|
||||
VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = OT_ERROR_FAILED);
|
||||
|
||||
mbedtls_mpi_init(&rMpi);
|
||||
mbedtls_mpi_init(&sMpi);
|
||||
|
||||
// Sign using ECDSA.
|
||||
VerifyOrExit(mbedtls_ecdsa_sign(&ctx.grp, &rMpi, &sMpi, &ctx.d, aInputHash, aInputHashLength, FillRandom, NULL) ==
|
||||
0,
|
||||
error = OT_ERROR_FAILED);
|
||||
VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= *aOutputLength, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
// Concatenate the two octet sequences in the order R and then S.
|
||||
VerifyOrExit(mbedtls_mpi_write_binary(&rMpi, aOutput, mbedtls_mpi_size(&rMpi)) == 0, error = OT_ERROR_FAILED);
|
||||
*aOutputLength = mbedtls_mpi_size(&rMpi);
|
||||
|
||||
VerifyOrExit(mbedtls_mpi_write_binary(&sMpi, aOutput + *aOutputLength, mbedtls_mpi_size(&sMpi)) == 0,
|
||||
error = OT_ERROR_FAILED);
|
||||
*aOutputLength += mbedtls_mpi_size(&sMpi);
|
||||
|
||||
exit:
|
||||
mbedtls_mpi_free(&rMpi);
|
||||
mbedtls_mpi_free(&sMpi);
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
mbedtls_pk_free(&pkCtx);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int Ecdsa::FillRandom(void *, unsigned char *aBuffer, size_t aSize)
|
||||
{
|
||||
Random::FillBuffer(aBuffer, aSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_ENABLE_ECDSA
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 includes definitions for performing ECDSA signing.
|
||||
*/
|
||||
|
||||
#ifndef ECDSA_HPP_
|
||||
#define ECDSA_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "utils/wrap_stdint.h"
|
||||
|
||||
#include <openthread/error.h>
|
||||
|
||||
namespace ot {
|
||||
namespace Crypto {
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements ECDSA signing.
|
||||
*
|
||||
*/
|
||||
class Ecdsa
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method creates ECDSA sign.
|
||||
*
|
||||
* @param[out] aOutput An output buffer where ECDSA sign should be stored.
|
||||
* @param[inout] aOutputLength The length of the @p aOutput buffer.
|
||||
* @param[in] aInputHash An input hash.
|
||||
* @param[in] aInputHashLength The length of the @p aInputHash buffer.
|
||||
* @param[in] aPrivateKey A private key in PEM format.
|
||||
* @param[in] aPrivateKeyLength The length of the @p aPrivateKey buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE ECDSA sign has been created successfully.
|
||||
* @retval OT_ERROR_NO_BUFS Output buffer is too small.
|
||||
* @retval OT_ERROR_INVALID_ARGS Private key is not valid EC Private Key.
|
||||
* @rerval OT_ERROR_FAILED Error during signing.
|
||||
*/
|
||||
static otError Sign(uint8_t * aOutput,
|
||||
uint16_t * aOutputLength,
|
||||
const uint8_t *aInputHash,
|
||||
uint16_t aInputHashLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint16_t aPrivateKeyLength);
|
||||
|
||||
private:
|
||||
static int FillRandom(void *, unsigned char *aBuffer, size_t aSize);
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace ot
|
||||
|
||||
#endif // ECDSA_HPP_
|
||||
Vendored
+9
-1
@@ -119,6 +119,14 @@ __inline int windows_kernel_snprintf(char * s, size_t n, const char * format, ..
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_ECDSA
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */
|
||||
#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */
|
||||
#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */
|
||||
@@ -127,7 +135,7 @@ __inline int windows_kernel_snprintf(char * s, size_t n, const char * format, ..
|
||||
#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */
|
||||
|
||||
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
|
||||
#define MBEDTLS_PLATFORM_STD_CALLOC otPlatCAlloc /**< Default allocator to use, can be undefined */
|
||||
#define MBEDTLS_PLATFORM_STD_CALLOC otPlatCAlloc /**< Default allocator to use, can be undefined */
|
||||
#define MBEDTLS_PLATFORM_STD_FREE otPlatFree /**< Default free to use, can be undefined */
|
||||
#else
|
||||
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
|
||||
Reference in New Issue
Block a user