Skip to content

Commit

Permalink
Berry add AES CCM decrypting in a single call to avoid any object all…
Browse files Browse the repository at this point in the history
…ocation (#19153)
  • Loading branch information
s-hadinger committed Jul 19, 2023
1 parent 2a3690b commit 3da5124
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
- Berry add `energy.update_total()` to call `EnergyUpdateTotal()` from energy driver
- Berry add metrics for memory allocation/deallocation/reallocation
- Berry `tasmota.loglevel()` and `tasmota.rtc_utc()` for faster performance
- Berry add AES CCM decrypting in a single call to avoid any object allocation

### Breaking Changed

Expand Down
11 changes: 7 additions & 4 deletions lib/libesp32/berry_tasmota/src/be_crypto_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ 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);
extern int m_aes_ccm_encrypt(bvm *vm);
extern int m_aes_ccm_decrypt(bvm *vm);
extern int m_aes_ccm_decrypt1(bvm *vm);
extern int m_aes_ccm_tag(bvm *vm);

extern int m_aes_gcm_init(bvm *vm);
Expand Down Expand Up @@ -134,9 +135,11 @@ class be_class_aes_ccm (scope: global, name: AES_CCM) {
.p2, var
init, func(m_aes_ccm_init)
encrypt, func(m_aes_ccm_encryt)
decrypt, func(m_aes_ccm_decryt)
encrypt, func(m_aes_ccm_encrypt)
decrypt, func(m_aes_ccm_decrypt)
tag, func(m_aes_ccm_tag)
decrypt1, static_func(m_aes_ccm_decrypt1)
}
class be_class_aes_gcm (scope: global, name: AES_GCM) {
Expand Down
107 changes: 105 additions & 2 deletions tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_crypto.ino
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ extern "C" {

// 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(bvm *vm) { return m_aes_ccm_encrypt_or_decryt(vm, 1); }
int32_t m_aes_ccm_decrypt(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)) {
Expand Down Expand Up @@ -346,6 +346,109 @@ extern "C" {
} while (0);
be_raise(vm, kTypeError, nullptr);
}

// `AES_CCM.decrypt1(
// secret_key:bytes(16 or 32),
// iv:bytes(), iv_start:int, iv_len:int (7..13),
// aad:bytes(), aad_start:int, aad_len:int,
// data:bytes(), data_start:int, data_len:int,
// tag:bytes(), tag_start:int, tag_len:int (4..16))
// -> bool (true if tag matches)
//
// all-in-one decrypt function
// decryption in place
//
int32_t m_aes_ccm_decrypt1(struct bvm *vm);
int32_t m_aes_ccm_decrypt1(struct bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 13 && be_isbytes(vm, 1) // secret_key
&& be_isbytes(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) // iv, iv_start, iv_len
&& be_isbytes(vm, 5) && be_isint(vm, 6) && be_isint(vm, 7) // aad, aad_start, aad_len
&& be_isbytes(vm, 8) && be_isint(vm, 9) && be_isint(vm, 10) // data_start, data_len
&& be_isbytes(vm, 11) && be_isint(vm, 12) && be_isint(vm, 13)) { // tag, tag_start, tag_len

size_t key_len = 0;
const void * key = be_tobytes(vm, 1, &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 uint8_t * nonce = (const uint8_t *) be_tobytes(vm, 2, &nonce_len);
int32_t n_start = be_toint(vm, 3);
int32_t n_len = be_toint(vm, 4);
if (n_start < 0 || n_len < 0 || n_start > nonce_len || n_start+n_len > nonce_len) {
be_raise(vm, "range_error", "out of range start/end");
}
nonce += n_start;
nonce_len = n_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 uint8_t * aad = (const uint8_t *) be_tobytes(vm, 5, &aad_len);
int32_t a_start = be_toint(vm, 6);
int32_t a_len = be_toint(vm, 7);
if (a_start < 0 || a_len < 0 || a_start > aad_len || a_start+a_len > aad_len) {
be_raise(vm, "range_error", "out of range start/end");
}
aad += a_start;
aad_len = a_len;

size_t data_len = 0;
uint8_t * data = (uint8_t *) be_tobytes(vm, 8, &data_len);
int32_t d_start = be_toint(vm, 9);
int32_t d_len = be_toint(vm, 10);
if (d_start < 0 || d_len < 0 || d_start > data_len || d_start+d_len > data_len) {
be_raise(vm, "range_error", "out of range start/end");
}
data += d_start;
data_len = d_len;

size_t tag_len = 0;
uint8_t * tag = (uint8_t *) be_tobytes(vm, 11, &tag_len);
int32_t t_start = be_toint(vm, 12);
int32_t t_len = be_toint(vm, 13);
if (t_start < 0 || t_len < 0 || t_start > tag_len || t_start+t_len > tag_len) {
be_raise(vm, "range_error", "out of range start/end");
}
tag += t_start;
tag_len = t_len;
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_aes_small_ctrcbc_keys key_ctx;
br_ccm_context ccm_ctx;
br_aes_small_ctrcbc_init(&key_ctx, key, key_len);
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"); }

if (aad_len > 0) {
br_ccm_aad_inject(&ccm_ctx, aad, aad_len);
}
br_ccm_flip(&ccm_ctx);

br_ccm_run(&ccm_ctx, 0 /*decrypt*/, data, data_len); // decrypt in place

// check tag
// create a bytes buffer of 16 bytes
uint8_t tag_computed[16] = {};
br_ccm_get_tag(&ccm_ctx, tag_computed);
if (memcmp(tag_computed, tag, tag_len) == 0) {
be_pushbool(vm, btrue);
} else {
be_pushbool(vm, bfalse);
}

// success
be_return(vm);
}
be_raise(vm, kTypeError, nullptr);
}
}

/*********************************************************************************************\
Expand Down

0 comments on commit 3da5124

Please sign in to comment.