mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-08 11:26:31 +00:00
Berry `crypto.AES_CCM
` (required by Matter protocol) (#17586)
This commit is contained in:
parent
f570dcc913
commit
d59caa7203
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
### Added
|
### Added
|
||||||
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich (#17557)
|
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich (#17557)
|
||||||
- Berry `bytes()` now evaluates to `false` if empty
|
- Berry `bytes()` now evaluates to `false` if empty
|
||||||
|
- Berry ``crypto.AES_CCM`` (required by Matter protocol)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
extern int be_class_crypto_member(bvm *vm);
|
extern int be_class_crypto_member(bvm *vm);
|
||||||
extern int m_crypto_random(bvm *vm);
|
extern int m_crypto_random(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);
|
||||||
|
extern int m_aes_ccm_tag(bvm *vm);
|
||||||
|
|
||||||
extern int m_aes_gcm_init(bvm *vm);
|
extern int m_aes_gcm_init(bvm *vm);
|
||||||
extern int m_aes_gcm_encryt(bvm *vm);
|
extern int m_aes_gcm_encryt(bvm *vm);
|
||||||
extern int m_aes_gcm_decryt(bvm *vm);
|
extern int m_aes_gcm_decryt(bvm *vm);
|
||||||
@ -47,6 +52,7 @@ extern const bclass be_class_md5;
|
|||||||
#include "solidify/solidified_crypto_pbkdf2_hmac_sha256.h"
|
#include "solidify/solidified_crypto_pbkdf2_hmac_sha256.h"
|
||||||
#include "solidify/solidified_crypto_spake2p_matter.h"
|
#include "solidify/solidified_crypto_spake2p_matter.h"
|
||||||
|
|
||||||
|
#include "be_fixed_be_class_aes_ccm.h"
|
||||||
#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_aes_ctr.h"
|
||||||
#include "be_fixed_be_class_ec_p256.h"
|
#include "be_fixed_be_class_ec_p256.h"
|
||||||
@ -65,11 +71,17 @@ extern const bclass be_class_md5;
|
|||||||
#define USE_BERRY_CRYPTO_HMAC_SHA256
|
#define USE_BERRY_CRYPTO_HMAC_SHA256
|
||||||
#undef USE_BERRY_CRYPTO_HKDF_SHA256
|
#undef USE_BERRY_CRYPTO_HKDF_SHA256
|
||||||
#define USE_BERRY_CRYPTO_HKDF_SHA256
|
#define USE_BERRY_CRYPTO_HKDF_SHA256
|
||||||
|
#undef USE_BERRY_CRYPTO_AES_CCM
|
||||||
|
#define USE_BERRY_CRYPTO_AES_CCM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const be_const_member_t be_crypto_members[] = {
|
const be_const_member_t be_crypto_members[] = {
|
||||||
// name with prefix '/' indicates a Berry class
|
// name with prefix '/' indicates a Berry class
|
||||||
// entries need to be sorted (ignoring the prefix char)
|
// entries need to be sorted (ignoring the prefix char)
|
||||||
|
#ifdef USE_BERRY_CRYPTO_AES_CCM
|
||||||
|
{ "/AES_CCM", (intptr_t) &be_class_aes_ccm },
|
||||||
|
#endif // USE_BERRY_CRYPTO_AES_CTR
|
||||||
|
|
||||||
#ifdef USE_BERRY_CRYPTO_AES_CTR
|
#ifdef USE_BERRY_CRYPTO_AES_CTR
|
||||||
{ "/AES_CTR", (intptr_t) &be_class_aes_ctr },
|
{ "/AES_CTR", (intptr_t) &be_class_aes_ctr },
|
||||||
#endif // USE_BERRY_CRYPTO_AES_CTR
|
#endif // USE_BERRY_CRYPTO_AES_CTR
|
||||||
@ -114,6 +126,16 @@ const size_t be_crypto_members_size = sizeof(be_crypto_members)/sizeof(be_crypto
|
|||||||
|
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
|
|
||||||
|
class be_class_aes_ccm (scope: global, name: AES_CCM) {
|
||||||
|
.p1, var
|
||||||
|
.p2, var
|
||||||
|
|
||||||
|
init, func(m_aes_ccm_init)
|
||||||
|
encrypt, func(m_aes_ccm_encryt)
|
||||||
|
decrypt, func(m_aes_ccm_decryt)
|
||||||
|
tag, func(m_aes_ccm_tag)
|
||||||
|
}
|
||||||
|
|
||||||
class be_class_aes_gcm (scope: global, name: AES_GCM) {
|
class be_class_aes_gcm (scope: global, name: AES_GCM) {
|
||||||
.p1, var
|
.p1, var
|
||||||
.p2, var
|
.p2, var
|
||||||
|
@ -1120,7 +1120,8 @@
|
|||||||
// #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_AES_CCM // enable AES CCM 128 bits
|
||||||
|
// #define USE_BERRY_CRYPTO_AES_CTR // enable AES CTR 256 bits
|
||||||
// #define USE_BERRY_CRYPTO_EC_P256 // enable EC P256r1
|
// #define USE_BERRY_CRYPTO_EC_P256 // enable EC P256r1
|
||||||
// #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
|
||||||
|
@ -180,6 +180,122 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* AES_CCM class
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// `AES_CCM.init(secret_key:bytes(16 or 32), iv:bytes(7..13), aad:bytes(), data_len:int, tag_len:int) -> instance`
|
||||||
|
//
|
||||||
|
int32_t m_aes_ccm_init(struct bvm *vm);
|
||||||
|
int32_t m_aes_ccm_init(struct bvm *vm) {
|
||||||
|
int32_t argc = be_top(vm); // Get the number of arguments
|
||||||
|
if (argc >= 6 && be_isbytes(vm, 2) && be_isbytes(vm, 3) && be_isbytes(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6)) {
|
||||||
|
do {
|
||||||
|
size_t key_len = 0;
|
||||||
|
const void * key = be_tobytes(vm, 2, &key_len);
|
||||||
|
if (key_len != 32 && key_len != 16) {
|
||||||
|
be_raise(vm, "value_error", "Key size must be 16 or 32 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nonce_len = 0;
|
||||||
|
const void * nonce = be_tobytes(vm, 3, &nonce_len);
|
||||||
|
if (nonce_len < 7 || nonce_len > 13) {
|
||||||
|
be_raise(vm, "value_error", "Nonce size must be 7..13");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t aad_len = 0;
|
||||||
|
const void * aad = be_tobytes(vm, 4, &aad_len);
|
||||||
|
|
||||||
|
int32_t data_len = be_toint(vm, 5);
|
||||||
|
|
||||||
|
int32_t tag_len = be_toint(vm, 6);
|
||||||
|
if (tag_len < 4 || tag_len > 16) {
|
||||||
|
be_raise(vm, "value_error", "Tag size must be 4..16");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize an AES CCM structure with the secret key
|
||||||
|
br_ccm_context * ccm_ctx = (br_ccm_context *) be_os_malloc(sizeof(br_ccm_context));
|
||||||
|
if (!ccm_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
|
||||||
|
|
||||||
|
be_newcomobj(vm, ccm_ctx, &be_commonobj_destroy_generic);
|
||||||
|
be_setmember(vm, 1, ".p1");
|
||||||
|
|
||||||
|
br_aes_small_ctrcbc_keys * key_ctx = (br_aes_small_ctrcbc_keys *) be_os_malloc(sizeof(br_aes_small_ctrcbc_keys));
|
||||||
|
if (!key_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
|
||||||
|
br_aes_small_ctrcbc_init(key_ctx, key, key_len);
|
||||||
|
be_newcomobj(vm, key_ctx, &be_commonobj_destroy_generic);
|
||||||
|
be_setmember(vm, 1, ".p2");
|
||||||
|
|
||||||
|
br_ccm_init(ccm_ctx, &key_ctx->vtable);
|
||||||
|
int ret = br_ccm_reset(ccm_ctx, nonce, nonce_len, aad_len, data_len, tag_len);
|
||||||
|
if (ret == 0) { be_raise(vm, "value_error", "br_ccm_reset failed"); }
|
||||||
|
|
||||||
|
br_ccm_aad_inject(ccm_ctx, aad, aad_len);
|
||||||
|
br_ccm_flip(ccm_ctx);
|
||||||
|
|
||||||
|
be_return_nil(vm);
|
||||||
|
// success
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish injection of authentication data
|
||||||
|
int32_t m_aes_ccm_encrypt_or_decryt(bvm *vm, int encrypt);
|
||||||
|
int32_t m_aes_ccm_encryt(bvm *vm) { return m_aes_ccm_encrypt_or_decryt(vm, 1); }
|
||||||
|
int32_t m_aes_ccm_decryt(bvm *vm) { return m_aes_ccm_encrypt_or_decryt(vm, 0); }
|
||||||
|
int32_t m_aes_ccm_encrypt_or_decryt(bvm *vm, int encrypt) {
|
||||||
|
int32_t argc = be_top(vm); // Get the number of arguments
|
||||||
|
if (argc >= 2 && be_isbytes(vm, 2)) {
|
||||||
|
do {
|
||||||
|
// get CCM context
|
||||||
|
be_getmember(vm, 1, ".p1");
|
||||||
|
br_ccm_context * ccm_ctx = (br_ccm_context *) be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
br_ccm_run(ccm_ctx, encrypt, bytes, length);
|
||||||
|
|
||||||
|
be_return(vm);
|
||||||
|
// success
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t m_aes_ccm_tag(bvm *vm) {
|
||||||
|
do {
|
||||||
|
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
|
||||||
|
|
||||||
|
// get CCM context
|
||||||
|
be_getmember(vm, 1, ".p1");
|
||||||
|
br_ccm_context * ccm_ctx = (br_ccm_context *) be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// create a bytes buffer of 16 bytes
|
||||||
|
uint8_t tag[16] = {};
|
||||||
|
br_ccm_get_tag(ccm_ctx, tag);
|
||||||
|
be_pushbytes(vm, tag, sizeof(tag));
|
||||||
|
|
||||||
|
be_return(vm);
|
||||||
|
// success
|
||||||
|
} while (0);
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* AES_CTR class
|
* AES_CTR class
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user