summaryrefslogtreecommitdiff
path: root/vere/pkg/noun/jets/e/aes_siv.c
diff options
context:
space:
mode:
Diffstat (limited to 'vere/pkg/noun/jets/e/aes_siv.c')
-rw-r--r--vere/pkg/noun/jets/e/aes_siv.c370
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));
+ }
+}