Berry add crypto AES_CTR, HDMAC_SHA256, MD5 (#17451)

This commit is contained in:
s-hadinger 2022-12-19 22:30:54 +01:00 committed by GitHub
parent 59fc09acc4
commit d670f476ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 208 additions and 10 deletions

View File

@ -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) - Support for IPv6 DNS records (AAAA) and IPv6 ``Ping`` for ESP32 and ESP8266 (#17417)
- Berry support for ``crypto.SHA256`` (#17430) - Berry support for ``crypto.SHA256`` (#17430)
- Support for RGB displays (#17414) - Support for RGB displays (#17414)
- Berry add crypto AES_CTR, HDMAC_SHA256, MD5
### Breaking Changed ### Breaking Changed

View File

@ -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_decryt(bvm *vm);
extern int m_aes_gcm_tag(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_pubkey(bvm *vm);
extern int m_ec_c25519_sharedkey(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_update(bvm *vm);
extern int m_hash_sha256_out(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_gcm.h"
#include "be_fixed_be_class_aes_ctr.h"
#include "be_fixed_be_class_ec_c25519.h" #include "be_fixed_be_class_ec_c25519.h"
#include "be_fixed_be_class_sha256.h" #include "be_fixed_be_class_sha256.h"
#include "be_fixed_be_class_hmac_sha256.h"
#include "be_fixed_crypto.h" #include "be_fixed_crypto.h"
/* @const_object_info_begin /* @const_object_info_begin
@ -36,6 +48,14 @@ class be_class_aes_gcm (scope: global, name: AES_GCM) {
tag, func(m_aes_gcm_tag) 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) { class be_class_ec_c25519 (scope: global, name: EC_C25519) {
public_key, func(m_ec_c25519_pubkey) public_key, func(m_ec_c25519_pubkey)
shared_key, func(m_ec_c25519_sharedkey) 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) 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) { module crypto (scope: global) {
AES_GCM, class(be_class_aes_gcm) AES_GCM, class(be_class_aes_gcm)
AES_CTR, class(be_class_aes_ctr)
EC_C25519, class(be_class_ec_c25519) EC_C25519, class(be_class_ec_c25519)
SHA256, class(be_class_sha256) SHA256, class(be_class_sha256)
HMAC_SHA256, class(be_class_hmac_sha256)
MD5, class(be_class_md5)
} }
@const_object_info_end */ @const_object_info_end */

View File

@ -11,8 +11,8 @@
#include "esp_rom_md5.h" #include "esp_rom_md5.h"
// `Md5.init() -> ` // `Md5.init() -> `
int32_t m_md5_init(struct bvm *vm); int m_md5_init(bvm *vm);
int32_t m_md5_init(struct bvm *vm) { int m_md5_init(bvm *vm) {
md5_context_t * ctx = (md5_context_t *) be_os_malloc(sizeof(md5_context_t)); md5_context_t * ctx = (md5_context_t *) be_os_malloc(sizeof(md5_context_t));
if (!ctx) { if (!ctx) {
@ -28,13 +28,11 @@ int32_t m_md5_init(struct bvm *vm) {
// `Md5.update(content:bytes()) -> nil` // `Md5.update(content:bytes()) -> nil`
// //
// Add raw bytes to the MD5 calculation // Add raw bytes to the MD5 calculation
int32_t m_md5_update(struct bvm *vm); int m_md5_update(bvm *vm);
int32_t m_md5_update(struct bvm *vm) { int m_md5_update(bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments 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 { 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; size_t length = 0;
const void * bytes = be_tobytes(vm, 2, &length); const void * bytes = be_tobytes(vm, 2, &length);
if (!bytes) break; if (!bytes) break;
@ -57,8 +55,8 @@ int32_t m_md5_update(struct bvm *vm) {
// `Md5.update(content:bytes()) -> nil` // `Md5.update(content:bytes()) -> nil`
// //
// Add raw bytes to the MD5 calculation // Add raw bytes to the MD5 calculation
int32_t m_md5_finish(struct bvm *vm); int m_md5_finish(bvm *vm);
int32_t m_md5_finish(struct bvm *vm) { int m_md5_finish(bvm *vm) {
be_getmember(vm, 1, ".p"); be_getmember(vm, 1, ".p");
md5_context_t * ctx; md5_context_t * ctx;
ctx = (md5_context_t *) be_tocomptr(vm, -1); ctx = (md5_context_t *) be_tocomptr(vm, -1);

View File

@ -1106,8 +1106,10 @@
// #define USE_BERRY_ULP // Enable ULP (Ultra Low Power) support (+4.9k) // #define USE_BERRY_ULP // Enable ULP (Ultra Low Power) support (+4.9k)
// Berry crypto extensions below: // Berry crypto extensions below:
#define USE_BERRY_CRYPTO_AES_GCM // enable AES GCM 256 bits #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_EC_C25519 // enable Elliptic Curve C C25519
#define USE_BERRY_CRYPTO_SHA256 // enable SHA256 hash function #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 #define USE_CSE7761 // Add support for CSE7761 Energy monitor as used in Sonoff Dual R3
// -- LVGL Graphics Library --------------------------------- // -- LVGL Graphics Library ---------------------------------

View File

@ -25,7 +25,7 @@
#include "be_object.h" #include "be_object.h"
/*********************************************************************************************\ /*********************************************************************************************\
* AES class * AES_GCM class
* *
\*********************************************************************************************/ \*********************************************************************************************/
extern "C" { extern "C" {
@ -158,6 +158,87 @@ extern "C" {
#endif // USE_BERRY_CRYPTO_AES_GCM #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 * 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 * EC C25519 class
* *