firmware/external/c-modules/aes256ctr/module.c
2021-03-01 09:03:03 -05:00

188 lines
5.2 KiB
C

//
// module top-level
//
#include "py/obj.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "aes_256_ctr.h"
#if MICROPY_ENABLE_DYNRUNTIME
#error "Static Only"
#endif
// AES block size
#define BLKSIZE 16
typedef struct {
mp_obj_base_t base;
uint8_t runt[BLKSIZE];
int runt_len;
param p;
} mp_obj_AES256CTR_t;
STATIC const mp_obj_type_t s_AES256CTR_type;
STATIC mp_obj_t s_AES256CTR_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// args: key, nonce
mp_arg_check_num(n_args, n_kw, 1, 2, false);
mp_buffer_info_t key;
mp_get_buffer_raise(args[0], &key, MP_BUFFER_READ);
if(key.len != 32) {
// only AES-256 here
mp_raise_ValueError(NULL);
}
mp_obj_AES256CTR_t *o = m_new_obj_with_finaliser(mp_obj_AES256CTR_t);
o->base.type = type;
// state setup, and key schedule
memset(&o->p, 0, sizeof(param));
o->runt_len = 0;
if(n_args == 2) {
mp_buffer_info_t n_in;
mp_get_buffer_raise(args[1], &n_in, MP_BUFFER_READ);
if(n_in.len > 16) {
mp_raise_ValueError(NULL);
}
// can be 12 bytes of nonce + 4 bytes ctr, or just all 16 bytes of state
memcpy(o->p.nonce, n_in.buf, n_in.len);
}
// key setup
memcpy(o->p.rk, key.buf, 32);
AES_256_keyschedule(key.buf, o->p.rk+32);
return o;
}
static bool inline
is_unaligned(const void *p)
{
return !!(((uint32_t)p) & 0x3);
}
STATIC mp_obj_t s_AES256CTR_cipher(mp_obj_t self_in, mp_obj_t buf_in)
{
mp_obj_AES256CTR_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t buf;
mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ);
int len = buf.len, in_len = buf.len;
const uint8_t *inp = buf.buf;
uint8_t *rv = m_malloc(in_len);
uint8_t *outp = rv;
if(self->runt_len) {
// we've already encrypted (w/ zero bytes) for this part
uint8_t *ch = &self->runt[BLKSIZE - self->runt_len];
while(self->runt_len && in_len) {
*(outp++) = *(inp++) ^ *(ch++);
self->runt_len --;
in_len --;
}
}
bool nogood = (is_unaligned(inp) || is_unaligned(outp));
while(in_len) {
if(in_len >= BLKSIZE) {
if(nogood) {
uint8_t blk[BLKSIZE];
// align data so ASM can work
memcpy(blk, inp, BLKSIZE);
AES_256_encrypt_ctr(&self->p, blk, blk, BLKSIZE);
memcpy(outp, blk, BLKSIZE);
} else {
// rare? but faster case
AES_256_encrypt_ctr(&self->p, inp, outp, BLKSIZE);
}
outp += BLKSIZE;
inp += BLKSIZE;
in_len -= BLKSIZE;
} else {
uint8_t blk[BLKSIZE] = {};
memcpy(blk, inp, in_len);
AES_256_encrypt_ctr(&self->p, blk, self->runt, BLKSIZE);
memcpy(outp, self->runt, in_len);
self->runt_len = BLKSIZE - in_len;
in_len = 0;
}
// inc counter (big endian, assumes nonce != ~0)
uint8_t *ctr = &self->p.ctr[3];
while(1) {
ctr[0] += 1;
if(ctr[0]) break;
ctr--;
}
}
return mp_obj_new_bytearray_by_ref(len, rv);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(s_AES256CTR_cipher_obj, s_AES256CTR_cipher);
STATIC mp_obj_t s_AES256CTR_copy(mp_obj_t self_in) {
mp_obj_AES256CTR_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_AES256CTR_t *rv = m_new_obj_with_finaliser(mp_obj_AES256CTR_t);
*rv = *self;
rv->base.type = &s_AES256CTR_type;
return rv;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(s_AES256CTR_copy_obj, s_AES256CTR_copy);
STATIC mp_obj_t s_AES256CTR_blank(mp_obj_t self_in) {
mp_obj_AES256CTR_t *self = MP_OBJ_TO_PTR(self_in);
// cf_aes_finish is just this anyway
memset(self, 0, sizeof(mp_obj_AES256CTR_t));
self->base.type = &s_AES256CTR_type;
return self_in;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(s_AES256CTR_blank_obj, s_AES256CTR_blank);
STATIC const mp_rom_map_elem_t s_AES256CTR_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_cipher), MP_ROM_PTR(&s_AES256CTR_cipher_obj) },
{ MP_ROM_QSTR(MP_QSTR_blank), MP_ROM_PTR(&s_AES256CTR_blank_obj) },
{ MP_ROM_QSTR(MP_QSTR_blank), MP_ROM_PTR(&s_AES256CTR_blank_obj) },
{ MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&s_AES256CTR_copy_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&s_AES256CTR_blank_obj) },
};
STATIC MP_DEFINE_CONST_DICT(s_AES256CTR_locals_dict, s_AES256CTR_locals_dict_table);
STATIC const mp_obj_type_t s_AES256CTR_type = {
{ &mp_type_type },
.name = MP_QSTR_AES256CTR,
.make_new = s_AES256CTR_make_new,
.locals_dict = (void *)&s_AES256CTR_locals_dict,
};
STATIC const mp_rom_map_elem_t mp_module_aes256ctr_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_aes256ctr) },
{ MP_ROM_QSTR(MP_QSTR_new), MP_ROM_PTR(&s_AES256CTR_type) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_aes256ctr_globals, mp_module_aes256ctr_globals_table);
const mp_obj_module_t mp_module_aes256ctr = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_aes256ctr_globals,
};
MP_REGISTER_MODULE(MP_QSTR_aes256ctr, mp_module_aes256ctr, 1);