diff options
Diffstat (limited to 'vere/pkg/noun/jets/e/aes_siv.c')
-rw-r--r-- | vere/pkg/noun/jets/e/aes_siv.c | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/vere/pkg/noun/jets/e/aes_siv.c b/vere/pkg/noun/jets/e/aes_siv.c new file mode 100644 index 0000000..f88ba6a --- /dev/null +++ b/vere/pkg/noun/jets/e/aes_siv.c @@ -0,0 +1,370 @@ +/// @file + +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" +#include "urcrypt.h" + +typedef int (*urcrypt_siv)(c3_y*, size_t, + urcrypt_aes_siv_data*, size_t, + c3_y*, c3_y[16], c3_y*); + + +// soc_w = number of items +// mat_w = size in bytes of assoc array +// dat_w = size of allocation (array + atom storage) +static void +_cqea_measure_ads(u3_noun ads, c3_w* soc_w, c3_w *mat_w, c3_w *dat_w) +{ + u3_noun i, t; + c3_w a_w, b_w, tmp_w; + + for ( a_w = b_w = 0, t = ads; u3_nul != t; ++a_w ) { + u3x_cell(t, &i, &t); + if ( c3n == u3ud(i) ) { + u3m_bail(c3__exit); + return; + } + else { + tmp_w = b_w; + b_w += u3r_met(3, i); + if ( b_w < tmp_w ) { + u3m_bail(c3__fail); + return; + } + } + } + + // check for size overflows + tmp_w = a_w * sizeof(urcrypt_aes_siv_data); + if ( (tmp_w / a_w) != sizeof(urcrypt_aes_siv_data) ) { + u3m_bail(c3__fail); + } + else if ( (*dat_w = tmp_w + b_w) < tmp_w ) { + u3m_bail(c3__fail); + } + else { + *soc_w = a_w; + *mat_w = tmp_w; + } +} + +// assumes ads is a valid (list @) because it's already been measured +static void +_cqea_encode_ads(u3_noun ads, + c3_w mat_w, + urcrypt_aes_siv_data *dat_u) +{ + c3_w met_w; + u3_noun i, t; + urcrypt_aes_siv_data *cur_u; + c3_y *dat_y = ((c3_y*) dat_u) + mat_w; + + for ( cur_u = dat_u, t = ads; u3_nul != t; t = u3t(t), ++cur_u ) { + i = u3h(t); + met_w = u3r_met(3, i); + u3r_bytes(0, met_w, dat_y, i); + cur_u->length = met_w; + cur_u->bytes = dat_y; + dat_y += met_w; + } +} + +static void +_cqea_ads_free(urcrypt_aes_siv_data *dat_u) +{ + if ( NULL != dat_u ) { + u3a_free(dat_u); + } +} + +static urcrypt_aes_siv_data* +_cqea_ads_alloc(u3_noun ads, c3_w *soc_w) +{ + if ( !ads ) { + *soc_w = 0; + return NULL; + } + else { + c3_w mat_w, dat_w; + urcrypt_aes_siv_data *dat_u; + + _cqea_measure_ads(ads, soc_w, &mat_w, &dat_w); + dat_u = u3a_malloc(dat_w); + _cqea_encode_ads(ads, mat_w, dat_u); + return dat_u; + } +} + +static u3_noun +_cqea_siv_en(c3_y* key_y, + c3_w key_w, + u3_noun ads, + u3_atom txt, + urcrypt_siv low_f) +{ + u3_noun ret; + c3_w txt_w, soc_w; + c3_y *txt_y, *out_y, iv_y[16]; + urcrypt_aes_siv_data *dat_u; + + dat_u = _cqea_ads_alloc(ads, &soc_w); + txt_y = u3r_bytes_all(&txt_w, txt); + out_y = u3a_malloc(txt_w); + + ret = ( 0 != (*low_f)(txt_y, txt_w, dat_u, soc_w, key_y, iv_y, out_y) ) + ? u3_none + : u3nt(u3i_bytes(16, iv_y), + u3i_words(1, &txt_w), + u3i_bytes(txt_w, out_y)); + + u3a_free(txt_y); + u3a_free(out_y); + _cqea_ads_free(dat_u); + return ret; +} + +static u3_noun +_cqea_siv_de(c3_y* key_y, + c3_w key_w, + u3_noun ads, + u3_atom iv, + u3_atom len, + u3_atom txt, + urcrypt_siv low_f) +{ + c3_w txt_w; + if ( !u3r_word_fit(&txt_w, len) ) { + return u3m_bail(c3__fail); + } + else { + u3_noun ret; + c3_w soc_w; + c3_y *txt_y, *out_y, iv_y[16]; + urcrypt_aes_siv_data *dat_u; + + u3r_bytes(0, 16, iv_y, iv); + dat_u = _cqea_ads_alloc(ads, &soc_w); + txt_y = u3r_bytes_alloc(0, txt_w, txt); + out_y = u3a_malloc(txt_w); + + if ( 0 != (*low_f)(txt_y, txt_w, dat_u, soc_w, key_y, iv_y, out_y) ) { + return u3m_bail(c3__evil); + } + + ret = u3nc(0, u3i_bytes(txt_w, out_y)); + + u3a_free(txt_y); + u3a_free(out_y); + _cqea_ads_free(dat_u); + + return ret; + } +} + +// the siv* hoon doesn't explicitly check keysizes, but all of these functions +// have fixed maximum keysizes, so we will punt if we get a key that is too +// large. + +static u3_noun +_cqea_siva_en(u3_atom key, + u3_noun ads, + u3_atom txt) +{ + if ( u3r_met(3, key) > 32 ) { + return u3_none; + } + else { + c3_y key_y[32]; + u3r_bytes(0, 32, key_y, key); + return _cqea_siv_en(key_y, 32, ads, txt, &urcrypt_aes_siva_en); + } +} + +u3_noun +u3wea_siva_en(u3_noun cor) +{ + u3_noun key, ads, txt; + + if ( c3n == u3r_mean(cor, u3x_sam, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("siva-en", _cqea_siva_en(key, ads, txt)); + } +} + +static u3_noun +_cqea_siva_de(u3_atom key, + u3_noun ads, + u3_atom iv, + u3_atom len, + u3_atom txt) +{ + if ( u3r_met(3, key) > 32 ) { + return u3_none; + } + else { + c3_y key_y[32]; + u3r_bytes(0, 32, key_y, key); + return _cqea_siv_de(key_y, 32, ads, iv, len, txt, &urcrypt_aes_siva_de); + } +} + +u3_noun +u3wea_siva_de(u3_noun cor) +{ + u3_noun key, ads, iv, len, txt; + + if ( c3n == u3r_mean(cor, + u3x_sam_2, &iv, + u3x_sam_6, &len, + u3x_sam_7, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("siva-de", _cqea_siva_de(key, ads, iv, len, txt)); + } +} + +static u3_noun +_cqea_sivb_en(u3_atom key, + u3_noun ads, + u3_atom txt) +{ + if ( u3r_met(3, key) > 48 ) { + return u3_none; + } + else { + c3_y key_y[48]; + u3r_bytes(0, 48, key_y, key); + return _cqea_siv_en(key_y, 48, ads, txt, &urcrypt_aes_sivb_en); + } +} + + +u3_noun +u3wea_sivb_en(u3_noun cor) +{ + u3_noun key, ads, txt; + + if ( c3n == u3r_mean(cor, u3x_sam, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("sivb-en", _cqea_sivb_en(key, ads, txt)); + } +} + +static u3_noun +_cqea_sivb_de(u3_atom key, + u3_noun ads, + u3_atom iv, + u3_atom len, + u3_atom txt) +{ + if ( u3r_met(3, key) > 48 ) { + return u3_none; + } + else { + c3_y key_y[48]; + u3r_bytes(0, 48, key_y, key); + return _cqea_siv_de(key_y, 48, ads, iv, len, txt, &urcrypt_aes_sivb_de); + } +} + +u3_noun +u3wea_sivb_de(u3_noun cor) +{ + u3_noun key, ads, iv, len, txt; + + if ( c3n == u3r_mean(cor, + u3x_sam_2, &iv, + u3x_sam_6, &len, + u3x_sam_7, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("sivb-de", _cqea_sivb_de(key, ads, iv, len, txt)); + } +} + +static u3_noun +_cqea_sivc_en(u3_atom key, + u3_noun ads, + u3_atom txt) +{ + if ( u3r_met(3, key) > 64 ) { + return u3_none; + } + else { + c3_y key_y[64]; + u3r_bytes(0, 64, key_y, key); + return _cqea_siv_en(key_y, 64, ads, txt, &urcrypt_aes_sivc_en); + } +} + +u3_noun +u3wea_sivc_en(u3_noun cor) +{ + u3_noun key, ads, txt; + + if ( c3n == u3r_mean(cor, u3x_sam, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("sivc-en", _cqea_sivc_en(key, ads, txt)); + } +} + +static u3_noun +_cqea_sivc_de(u3_atom key, + u3_noun ads, + u3_atom iv, + u3_atom len, + u3_atom txt) +{ + if ( u3r_met(3, key) > 64 ) { + return u3_none; + } + else { + c3_y key_y[64]; + u3r_bytes(0, 64, key_y, key); + return _cqea_siv_de(key_y, 64, ads, iv, len, txt, &urcrypt_aes_sivc_de); + } +} + +u3_noun +u3wea_sivc_de(u3_noun cor) +{ + u3_noun key, ads, iv, len, txt; + + if ( c3n == u3r_mean(cor, + u3x_sam_2, &iv, + u3x_sam_6, &len, + u3x_sam_7, &txt, + u3x_con_sam_2, &key, + u3x_con_sam_3, &ads, 0) || + c3n == u3ud(key) || + c3n == u3ud(txt) ) { + return u3m_bail(c3__exit); + } else { + return u3l_punt("sivc-de", _cqea_sivc_de(key, ads, iv, len, txt)); + } +} |