diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd13836b..2dbaa1d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - Matter bridge for ESP8266 remote endpoints (experimental) - Display descriptor for ST7735 128x160 display - Matter support for Occupancy via Switch (experimental) +- Berry RS256 crypto algorithm (RSASSA-MCKS1_v1-5 with SHA256) used for JWT ### Breaking Changed - Matter relay number starts at 1 instead of 0 to match Tasmota numbering diff --git a/lib/lib_ssl/bearssl-esp8266/src/t_inner.h b/lib/lib_ssl/bearssl-esp8266/src/t_inner.h index 924486db7..d5fecd71b 100644 --- a/lib/lib_ssl/bearssl-esp8266/src/t_inner.h +++ b/lib/lib_ssl/bearssl-esp8266/src/t_inner.h @@ -2597,7 +2597,11 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, #endif #define _debugBearSSL (0) - extern void optimistic_yield(uint32_t); + #ifdef ESP8266 + extern void optimistic_yield(uint32_t); + #else + #define optimistic_yield(ignored) + #endif #ifdef __cplusplus } #endif diff --git a/lib/libesp32/berry_tasmota/src/be_crypto_lib.c b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c index 621d17113..0162bc369 100644 --- a/lib/libesp32/berry_tasmota/src/be_crypto_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_crypto_lib.c @@ -11,6 +11,8 @@ extern int be_class_crypto_member(bvm *vm); extern int m_crypto_random(bvm *vm); +extern int m_rsa_rsassa_pkcs1_v1_5(bvm *vm); + extern int m_aes_ccm_init(bvm *vm); extern int m_aes_ccm_encryt(bvm *vm); extern int m_aes_ccm_decryt(bvm *vm); @@ -56,6 +58,7 @@ extern const bclass be_class_md5; #include "solidify/solidified_crypto_pbkdf2_hmac_sha256.h" #include "solidify/solidified_crypto_spake2p_matter.h" +#include "be_fixed_be_class_rsa.h" #include "be_fixed_be_class_aes_ccm.h" #include "be_fixed_be_class_aes_gcm.h" #include "be_fixed_be_class_aes_ctr.h" @@ -104,6 +107,10 @@ const be_const_member_t be_crypto_members[] = { { "/PBKDF2_HMAC_SHA256", (intptr_t) &be_class_pbkdf2_hmac_sha256 }, #endif // USE_BERRY_CRYPTO_PBKDF2_HMAC_SHA256 +#ifdef USE_BERRY_CRYPTO_RSA + { "/RSA", (intptr_t) &be_class_rsa }, +#endif // USE_BERRY_CRYPTO_PBKDF2_HMAC_SHA256 + #ifdef USE_BERRY_CRYPTO_SHA256 { "/SHA256", (intptr_t) &be_class_sha256 }, #endif // USE_BERRY_CRYPTO_SHA256 @@ -118,6 +125,10 @@ const size_t be_crypto_members_size = sizeof(be_crypto_members)/sizeof(be_crypto /* @const_object_info_begin +class be_class_rsa (scope: global, name: RSA) { + rs256, static_func(m_rsa_rsassa_pkcs1_v1_5) +} + class be_class_aes_ccm (scope: global, name: AES_CCM) { .p1, var .p2, var diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino index bec624546..d422f09d8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino @@ -65,6 +65,56 @@ extern "C" { } } +/*********************************************************************************************\ + * RSA class + * +\*********************************************************************************************/ +extern "C" { + // crypto.RSA.rsassa_pkcs1_v1_5(private_key:bytes(), msg:bytes()) -> bytes() + // Parses RSA private key from DER binary + int32_t m_rsa_rsassa_pkcs1_v1_5(bvm *vm); + int32_t m_rsa_rsassa_pkcs1_v1_5(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isbytes(vm, 1)) { + size_t sk_len = 0; + uint8_t * sk_der = (uint8_t*) be_tobytes(vm, 1, &sk_len); + + // 1. decode the DER private key + br_skey_decoder_context sdc; + br_skey_decoder_init(&sdc); + br_skey_decoder_push(&sdc, sk_der, sk_len); + if (int ret = br_skey_decoder_last_error(&sdc)) { + be_raisef(vm, "value_error", "invalid private key %i", ret); + } + if (br_skey_decoder_key_type(&sdc) != BR_KEYTYPE_RSA) { + be_raise(vm, "value_error", "key is not RSA"); + } + const br_rsa_private_key *sk = br_skey_decoder_get_rsa(&sdc); + + // 2. Hash the message with SHA + size_t msg_len = 0; + uint8_t * msg = (uint8_t*) be_tobytes(vm, 2, &msg_len); + uint8_t hash[32]; + br_sha256_context ctx; + br_sha256_init(&ctx); + br_sha256_update(&ctx, msg, msg_len); + br_sha256_out(&ctx, hash); + + // 3. sign the message + size_t sign_len = (sk->n_bitlen + 7) / 8; + uint8_t x[sign_len] = {}; + int err = br_rsa_i15_pkcs1_sign(BR_HASH_OID_SHA256, hash, sizeof(hash), sk, x); + if (err != 1) { + be_raisef(vm, "value_error", "signature failed %i", err); + } + + be_pushbytes(vm, x, sign_len); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } +} + /*********************************************************************************************\ * AES_GCM class *