mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-16 15:26:29 +00:00
Berry `crypto.EC_P256
` ECDSA signature (required by Matter protocol) (#17723)
This commit is contained in:
parent
e2c9a71c3b
commit
457f706d17
@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [12.3.1.4]
|
## [12.3.1.4]
|
||||||
### Added
|
### Added
|
||||||
|
- Berry ``crypto.EC_P256`` ECDSA signature (required by Matter protocol)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ extern int m_aes_ctr_tag(bvm *vm);
|
|||||||
|
|
||||||
extern int m_ec_p256_pubkey(bvm *vm);
|
extern int m_ec_p256_pubkey(bvm *vm);
|
||||||
extern int m_ec_p256_sharedkey(bvm *vm);
|
extern int m_ec_p256_sharedkey(bvm *vm);
|
||||||
|
extern int m_ec_p256_ecdsa_sign_sha256(bvm *vm);
|
||||||
|
extern int m_ec_p256_ecdsa_verify_sha256(bvm *vm);
|
||||||
extern int m_ec_p256_mod(bvm *vm);
|
extern int m_ec_p256_mod(bvm *vm);
|
||||||
extern int m_ec_p256_neg(bvm *vm);
|
extern int m_ec_p256_neg(bvm *vm);
|
||||||
extern int m_ec_p256_muladd(bvm *vm);
|
extern int m_ec_p256_muladd(bvm *vm);
|
||||||
@ -157,6 +159,8 @@ class be_class_aes_ctr (scope: global, name: AES_CTR) {
|
|||||||
class be_class_ec_p256 (scope: global, name: EC_P256) {
|
class be_class_ec_p256 (scope: global, name: EC_P256) {
|
||||||
public_key, static_func(m_ec_p256_pubkey)
|
public_key, static_func(m_ec_p256_pubkey)
|
||||||
shared_key, static_func(m_ec_p256_sharedkey)
|
shared_key, static_func(m_ec_p256_sharedkey)
|
||||||
|
ecdsa_sign_sha256, static_func(m_ec_p256_ecdsa_sign_sha256)
|
||||||
|
ecdsa_verify_sha256, static_func(m_ec_p256_ecdsa_verify_sha256)
|
||||||
mod, static_func(m_ec_p256_mod)
|
mod, static_func(m_ec_p256_mod)
|
||||||
neg, static_func(m_ec_p256_neg)
|
neg, static_func(m_ec_p256_neg)
|
||||||
muladd, static_func(m_ec_p256_muladd)
|
muladd, static_func(m_ec_p256_muladd)
|
||||||
|
@ -566,6 +566,82 @@ extern "C" {
|
|||||||
be_raise(vm, kTypeError, nullptr);
|
be_raise(vm, kTypeError, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// crypto.EC_P256().ecdsa_sign_sha256(my_private_key:bytes(32), message:bytes()) -> bytes(64)
|
||||||
|
// Sign with ECDSA SHA256
|
||||||
|
int32_t m_ec_p256_ecdsa_sign_sha256(bvm *vm);
|
||||||
|
int32_t m_ec_p256_ecdsa_sign_sha256(bvm *vm) {
|
||||||
|
int32_t argc = be_top(vm); // Get the number of arguments
|
||||||
|
if (argc >= 2 && be_isbytes(vm, 1) && be_isbytes(vm, 2)) {
|
||||||
|
size_t sk_len = 0;
|
||||||
|
uint8_t * sk = (uint8_t*) be_tobytes(vm, 1, &sk_len);
|
||||||
|
size_t msg_len = 0;
|
||||||
|
const uint8_t * msg = (const uint8_t*) be_tobytes(vm, 2, &msg_len);
|
||||||
|
if (sk_len != 32) {
|
||||||
|
be_raise(vm, "value_error", "Key size invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// first compute SHA-256 hash on the message
|
||||||
|
uint8_t hash[32];
|
||||||
|
br_sha256_context ctx;
|
||||||
|
br_sha256_init(&ctx);
|
||||||
|
br_sha256_update(&ctx, msg, msg_len);
|
||||||
|
br_sha256_out(&ctx, hash);
|
||||||
|
|
||||||
|
// run ECDSA on hash
|
||||||
|
uint8_t sign[64]; // hard limit for ECDSA SHA256
|
||||||
|
br_ec_private_key br_sk = { BR_EC_secp256r1, sk, 32 };
|
||||||
|
size_t sign_len = br_ecdsa_i15_sign_raw(&BR_EC_P256_IMPL, &br_sha256_vtable, hash, &br_sk, sign);
|
||||||
|
|
||||||
|
be_pushbytes(vm, sign, sign_len);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `crypto.EC_P256().ecdsa_verify_sha256(public_key:bytes(65), message:bytes(), hash:bytes()) -> bool`
|
||||||
|
// Verify signature with ECDSA SHA256
|
||||||
|
int32_t m_ec_p256_ecdsa_verify_sha256(bvm *vm);
|
||||||
|
int32_t m_ec_p256_ecdsa_verify_sha256(bvm *vm) {
|
||||||
|
int32_t argc = be_top(vm); // Get the number of arguments
|
||||||
|
if (argc >= 3 && be_isbytes(vm, 1) && be_isbytes(vm, 2) && be_isbytes(vm, 3)) {
|
||||||
|
size_t pk_len = 0;
|
||||||
|
uint8_t * pk = (uint8_t*) be_tobytes(vm, 1, &pk_len);
|
||||||
|
size_t msg_len = 0;
|
||||||
|
const uint8_t * msg = (const uint8_t*) be_tobytes(vm, 2, &msg_len);
|
||||||
|
if (pk_len != 65) {
|
||||||
|
be_raise(vm, "value_error", "Key size invalid");
|
||||||
|
}
|
||||||
|
size_t sig_len = 0;
|
||||||
|
const uint8_t * sig = (const uint8_t*) be_tobytes(vm, 3, &sig_len);
|
||||||
|
|
||||||
|
// first compute SHA-256 hash on the message
|
||||||
|
uint8_t hash[32];
|
||||||
|
br_sha256_context ctx;
|
||||||
|
br_sha256_init(&ctx);
|
||||||
|
br_sha256_update(&ctx, msg, msg_len);
|
||||||
|
br_sha256_out(&ctx, hash);
|
||||||
|
|
||||||
|
// run ECDSA on hash
|
||||||
|
br_ec_public_key br_pk = { BR_EC_secp256r1, pk, pk_len };
|
||||||
|
uint32_t ret = br_ecdsa_i15_vrfy_raw(&BR_EC_P256_IMPL, hash, sizeof(hash), &br_pk, sig, sig_len);
|
||||||
|
|
||||||
|
be_pushbool(vm, ret);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
/* Test values
|
||||||
|
import crypto
|
||||||
|
var priv = bytes('D42A43989B67211031FF194FBA791B5C3E03F9EC10ED561A4DEB2AA7BADB4772')
|
||||||
|
# var priv = crypto.random(32)
|
||||||
|
var pub = crypto.EC_P256().public_key(priv)
|
||||||
|
var msg = bytes().fromstring("Tasmota crypto ECDSA SECP256R1 SHA256 test message")
|
||||||
|
|
||||||
|
var sig = crypto.EC_P256().ecdsa_sign_sha256(priv, msg)
|
||||||
|
var ok = crypto.EC_P256().ecdsa_verify_sha256(pub, msg, sig)
|
||||||
|
assert(ok == true)
|
||||||
|
*/
|
||||||
|
|
||||||
// We have generated the P256 order as a i15 encoding using
|
// We have generated the P256 order as a i15 encoding using
|
||||||
// static const unsigned char P256_N[] PROGMEM = {
|
// static const unsigned char P256_N[] PROGMEM = {
|
||||||
// 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
// 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user