mirror of https://github.com/arendst/Tasmota.git
Berry add crypto AES_CTR, HDMAC_SHA256, MD5 (#17451)
This commit is contained in:
parent
59fc09acc4
commit
d670f476ba
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Support for IPv6 DNS records (AAAA) and IPv6 ``Ping`` for ESP32 and ESP8266 (#17417)
|
||||
- Berry support for ``crypto.SHA256`` (#17430)
|
||||
- Support for RGB displays (#17414)
|
||||
- Berry add crypto AES_CTR, HDMAC_SHA256, MD5
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ extern int m_aes_gcm_encryt(bvm *vm);
|
|||
extern int m_aes_gcm_decryt(bvm *vm);
|
||||
extern int m_aes_gcm_tag(bvm *vm);
|
||||
|
||||
extern int m_aes_ctr_init(bvm *vm);
|
||||
extern int m_aes_ctr_run(bvm *vm);
|
||||
extern int m_aes_ctr_tag(bvm *vm);
|
||||
|
||||
extern int m_ec_c25519_pubkey(bvm *vm);
|
||||
extern int m_ec_c25519_sharedkey(bvm *vm);
|
||||
|
||||
|
@ -19,9 +23,17 @@ extern int m_hash_sha256_init(bvm *vm);
|
|||
extern int m_hash_sha256_update(bvm *vm);
|
||||
extern int m_hash_sha256_out(bvm *vm);
|
||||
|
||||
extern int m_hmac_sha256_init(bvm *vm);
|
||||
extern int m_hmac_sha256_update(bvm *vm);
|
||||
extern int m_hmac_sha256_out(bvm *vm);
|
||||
|
||||
extern const bclass be_class_md5;
|
||||
|
||||
#include "be_fixed_be_class_aes_gcm.h"
|
||||
#include "be_fixed_be_class_aes_ctr.h"
|
||||
#include "be_fixed_be_class_ec_c25519.h"
|
||||
#include "be_fixed_be_class_sha256.h"
|
||||
#include "be_fixed_be_class_hmac_sha256.h"
|
||||
#include "be_fixed_crypto.h"
|
||||
|
||||
/* @const_object_info_begin
|
||||
|
@ -36,6 +48,14 @@ class be_class_aes_gcm (scope: global, name: AES_GCM) {
|
|||
tag, func(m_aes_gcm_tag)
|
||||
}
|
||||
|
||||
class be_class_aes_ctr (scope: global, name: AES_CTR) {
|
||||
.p1, var
|
||||
|
||||
init, func(m_aes_ctr_init)
|
||||
encrypt, func(m_aes_ctr_run)
|
||||
decrypt, func(m_aes_ctr_run)
|
||||
}
|
||||
|
||||
class be_class_ec_c25519 (scope: global, name: EC_C25519) {
|
||||
public_key, func(m_ec_c25519_pubkey)
|
||||
shared_key, func(m_ec_c25519_sharedkey)
|
||||
|
@ -49,10 +69,21 @@ class be_class_sha256 (scope: global, name: SHA256) {
|
|||
out, func(m_hash_sha256_out)
|
||||
}
|
||||
|
||||
class be_class_hmac_sha256 (scope: global, name: HMAC_SHA256) {
|
||||
.p, var
|
||||
|
||||
init, func(m_hmac_sha256_init)
|
||||
update, func(m_hmac_sha256_update)
|
||||
out, func(m_hmac_sha256_out)
|
||||
}
|
||||
|
||||
module crypto (scope: global) {
|
||||
AES_GCM, class(be_class_aes_gcm)
|
||||
AES_CTR, class(be_class_aes_ctr)
|
||||
EC_C25519, class(be_class_ec_c25519)
|
||||
SHA256, class(be_class_sha256)
|
||||
HMAC_SHA256, class(be_class_hmac_sha256)
|
||||
MD5, class(be_class_md5)
|
||||
}
|
||||
|
||||
@const_object_info_end */
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
#include "esp_rom_md5.h"
|
||||
|
||||
// `Md5.init() -> `
|
||||
int32_t m_md5_init(struct bvm *vm);
|
||||
int32_t m_md5_init(struct bvm *vm) {
|
||||
int m_md5_init(bvm *vm);
|
||||
int m_md5_init(bvm *vm) {
|
||||
|
||||
md5_context_t * ctx = (md5_context_t *) be_os_malloc(sizeof(md5_context_t));
|
||||
if (!ctx) {
|
||||
|
@ -28,13 +28,11 @@ int32_t m_md5_init(struct bvm *vm) {
|
|||
// `Md5.update(content:bytes()) -> nil`
|
||||
//
|
||||
// Add raw bytes to the MD5 calculation
|
||||
int32_t m_md5_update(struct bvm *vm);
|
||||
int32_t m_md5_update(struct bvm *vm) {
|
||||
int m_md5_update(bvm *vm);
|
||||
int m_md5_update(bvm *vm) {
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 2 && be_isinstance(vm, 2)) {
|
||||
if (argc >= 2 && be_isbytes(vm, 2)) {
|
||||
do {
|
||||
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
|
||||
if (!be_isderived(vm, 2)) break;
|
||||
size_t length = 0;
|
||||
const void * bytes = be_tobytes(vm, 2, &length);
|
||||
if (!bytes) break;
|
||||
|
@ -57,8 +55,8 @@ int32_t m_md5_update(struct bvm *vm) {
|
|||
// `Md5.update(content:bytes()) -> nil`
|
||||
//
|
||||
// Add raw bytes to the MD5 calculation
|
||||
int32_t m_md5_finish(struct bvm *vm);
|
||||
int32_t m_md5_finish(struct bvm *vm) {
|
||||
int m_md5_finish(bvm *vm);
|
||||
int m_md5_finish(bvm *vm) {
|
||||
be_getmember(vm, 1, ".p");
|
||||
md5_context_t * ctx;
|
||||
ctx = (md5_context_t *) be_tocomptr(vm, -1);
|
||||
|
|
|
@ -1106,8 +1106,10 @@
|
|||
// #define USE_BERRY_ULP // Enable ULP (Ultra Low Power) support (+4.9k)
|
||||
// Berry crypto extensions below:
|
||||
#define USE_BERRY_CRYPTO_AES_GCM // enable AES GCM 256 bits
|
||||
#define USE_BERRY_CRYPTO_AES_CTR // enable AEC CTR 256 bits
|
||||
// #define USE_BERRY_CRYPTO_EC_C25519 // enable Elliptic Curve C C25519
|
||||
#define USE_BERRY_CRYPTO_SHA256 // enable SHA256 hash function
|
||||
#define USE_BERRY_CRYPTO_HMAC_SHA256 // enable HMAC SHA256 hash function
|
||||
#define USE_CSE7761 // Add support for CSE7761 Energy monitor as used in Sonoff Dual R3
|
||||
|
||||
// -- LVGL Graphics Library ---------------------------------
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "be_object.h"
|
||||
|
||||
/*********************************************************************************************\
|
||||
* AES class
|
||||
* AES_GCM class
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
|
@ -158,6 +158,87 @@ extern "C" {
|
|||
#endif // USE_BERRY_CRYPTO_AES_GCM
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* AES_CTR class
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
|
||||
// `AES_CTR.init(secret_key:bytes(32)) -> instance`
|
||||
int32_t m_aes_ctr_init(struct bvm *vm);
|
||||
int32_t m_aes_ctr_init(struct bvm *vm) {
|
||||
#ifdef USE_BERRY_CRYPTO_AES_CTR
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 2 && be_isbytes(vm, 2)) {
|
||||
do {
|
||||
size_t length = 0;
|
||||
const void * bytes = be_tobytes(vm, 2, &length);
|
||||
if (!bytes) break;
|
||||
if (length != 32) {
|
||||
be_raise(vm, "value_error", "Key size must be 32 bytes");
|
||||
}
|
||||
|
||||
// Initialize an AES CTR structure with the secret key
|
||||
br_aes_small_ctr_keys * ctr_ctx = (br_aes_small_ctr_keys *) be_os_malloc(sizeof(br_aes_small_ctr_keys));
|
||||
if (!ctr_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
|
||||
br_aes_small_ctr_init(ctr_ctx, bytes, length);
|
||||
be_newcomobj(vm, ctr_ctx, &be_commonobj_destroy_generic);
|
||||
be_setmember(vm, 1, ".p1");
|
||||
|
||||
be_return_nil(vm);
|
||||
// success
|
||||
} while (0);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
#else // USE_BERRY_CRYPTO_AES_CTR
|
||||
be_raise(vm, "Not implemented", nullptr);
|
||||
#endif // USE_BERRY_CRYPTO_AES_CTR
|
||||
}
|
||||
|
||||
// `<instance:AES_CTR>.encrypt(content:bytes(), in:bytes(12), counter:int) -> nil`
|
||||
// `<instance:AES_CTR>.decrypt(content:bytes(), in:bytes(12), counter:int) -> nil`
|
||||
int32_t m_aes_ctr_run(bvm *vm);
|
||||
int32_t m_aes_ctr_run(bvm *vm) {
|
||||
#ifdef USE_BERRY_CRYPTO_AES_CTR
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 4 && be_isbytes(vm, 2) && be_isbytes(vm, 3) && be_isint(vm, 4)) {
|
||||
do {
|
||||
// get GCM context
|
||||
be_getmember(vm, 1, ".p1");
|
||||
br_aes_small_ctr_keys * ctx = (br_aes_small_ctr_keys *) be_tocomptr(vm, -1);
|
||||
be_pop(vm, 1);
|
||||
|
||||
size_t iv_len;
|
||||
const void * iv = be_tobytes(vm, 3, &iv_len);
|
||||
if (iv_len != 12) { be_raise(vm, "value_error", "IV size must be 12 bytes"); }
|
||||
|
||||
uint32_t counter = be_toint(vm, 4);
|
||||
|
||||
// copy the input buffer
|
||||
be_getmember(vm, 2, "copy"); // stack: bytes.copy()
|
||||
be_pushvalue(vm, 2); // stack: bytes.copy(), bytes instance
|
||||
be_call(vm, 1); // call copy with self parameter
|
||||
be_pop(vm, 1); // stack: clone of input bytes
|
||||
|
||||
size_t length = 0;
|
||||
// we are changing bytes in place
|
||||
void * bytes = (void*) be_tobytes(vm, -1, &length);
|
||||
if (!bytes) break;
|
||||
|
||||
uint32_t next_counter = br_aes_small_ctr_run(ctx, iv, counter, bytes, length);
|
||||
|
||||
be_return(vm);
|
||||
// success
|
||||
} while (0);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
#else // USE_BERRY_CRYPTO_AES_CTR
|
||||
be_raise(vm, "Not implemented", nullptr);
|
||||
#endif // USE_BERRY_CRYPTO_AES_CTR
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* SHA256 class
|
||||
*
|
||||
|
@ -236,6 +317,91 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* HMAC_SHA256 class
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
|
||||
// `HMAC_SHA256.init(key:bytes) -> nil`
|
||||
int32_t m_hmac_sha256_init(struct bvm *vm);
|
||||
int32_t m_hmac_sha256_init(struct bvm *vm) {
|
||||
#ifdef USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 2 && be_isbytes(vm, 2)) {
|
||||
// Initialize a HMAC context
|
||||
br_hmac_context * ctx = (br_hmac_context *) be_os_malloc(sizeof(br_hmac_context));
|
||||
if (!ctx) {
|
||||
be_throw(vm, BE_MALLOC_FAIL);
|
||||
}
|
||||
br_hmac_key_context keyCtx; // keyCtx can be allocated on stack, it is not needed after `br_hmac_init`
|
||||
size_t key_len;
|
||||
const void *key = be_tobytes(vm, 2, &key_len);
|
||||
br_hmac_key_init(&keyCtx, &br_sha256_vtable, key, key_len);
|
||||
br_hmac_init(ctx, &keyCtx, 0); // 0 is "natural output length"
|
||||
|
||||
be_newcomobj(vm, ctx, &be_commonobj_destroy_generic);
|
||||
be_setmember(vm, 1, ".p");
|
||||
be_return_nil(vm);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
#else // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
be_raise(vm, "Not implemented", nullptr);
|
||||
#endif // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
}
|
||||
|
||||
// `<instance:HMAC_SHA256>.update(content:bytes()) -> nil`
|
||||
//
|
||||
// Add raw bytes to the hash calculation
|
||||
int32_t m_hmac_sha256_update(struct bvm *vm);
|
||||
int32_t m_hmac_sha256_update(struct bvm *vm) {
|
||||
#ifdef USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 2 && be_isinstance(vm, 2)) {
|
||||
do {
|
||||
if (!be_isbytes(vm, 2)) break;
|
||||
size_t length = 0;
|
||||
const void * bytes = be_tobytes(vm, 2, &length);
|
||||
if (!bytes) break;
|
||||
|
||||
be_getmember(vm, 1, ".p");
|
||||
br_hmac_context * ctx;
|
||||
ctx = (br_hmac_context *) be_tocomptr(vm, -1);
|
||||
if (!ctx) break;
|
||||
|
||||
if (length > 0) {
|
||||
br_hmac_update(ctx, bytes, length);
|
||||
}
|
||||
be_return_nil(vm);
|
||||
// success
|
||||
} while (0);
|
||||
}
|
||||
be_raise(vm, "value_error", NULL);
|
||||
#else // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
be_raise(vm, "Not implemented", nullptr);
|
||||
#endif // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
}
|
||||
|
||||
// `<instance:SHA256>.finish() -> bytes()`
|
||||
//
|
||||
// Add raw bytes to the MD5 calculation
|
||||
int32_t m_hmac_sha256_out(struct bvm *vm);
|
||||
int32_t m_hmac_sha256_out(struct bvm *vm) {
|
||||
#ifdef USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
be_getmember(vm, 1, ".p");
|
||||
br_hmac_context * ctx;
|
||||
ctx = (br_hmac_context *) be_tocomptr(vm, -1);
|
||||
|
||||
uint8_t output[32];
|
||||
br_hmac_out(ctx, output);
|
||||
be_pushbytes(vm, output, sizeof(output));
|
||||
be_return(vm);
|
||||
#else // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
be_raise(vm, "Not implemented", nullptr);
|
||||
#endif // USE_BERRY_CRYPTO_HMAC_SHA256
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* EC C25519 class
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue