From 5981f4deffaee0f1df6b681dbc45a8ed9de36af9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 22 Sep 2022 11:31:38 -0400 Subject: [PATCH 01/54] u3: rewrites jam atom encoding to maximize its range --- pkg/noun/serial.c | 54 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/pkg/noun/serial.c b/pkg/noun/serial.c index 698a959d66..f994814fe1 100644 --- a/pkg/noun/serial.c +++ b/pkg/noun/serial.c @@ -36,7 +36,7 @@ struct _cs_jam_fib { /* _cs_jam_fib_grow(): reallocate buffer with fibonacci growth */ -static void +static inline void _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) { c3_w wan_w = fib_u->bit_w + mor_w; @@ -45,6 +45,7 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) // if ( wan_w < mor_w ) { u3m_bail(c3__fail); + return; } if ( wan_w > fib_u->a_w ) { @@ -64,7 +65,7 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) /* _cs_jam_fib_chop(): chop [met_w] bits of [a] into [fib_u] */ -static void +static inline void _cs_jam_fib_chop(struct _cs_jam_fib* fib_u, c3_w met_w, u3_noun a) { c3_w bit_w = fib_u->bit_w; @@ -86,12 +87,51 @@ _cs_jam_fib_mat(struct _cs_jam_fib* fib_u, u3_noun a) _cs_jam_fib_chop(fib_u, 1, 1); } else { - c3_w a_w = u3r_met(0, a); - c3_w b_w = c3_bits_word(a_w); + c3_w a_w = u3r_met(0, a); + c3_w b_w = c3_bits_word(a_w); + c3_w bit_w = fib_u->bit_w; + + // amortize overflow checks and reallocation + // + { + c3_w met_w = a_w + (2 * b_w); + + if ( a_w > (UINT32_MAX - 64) ) { + u3m_bail(c3__fail); + return; + } + + _cs_jam_fib_grow(fib_u, met_w); + fib_u->bit_w += met_w; + } - _cs_jam_fib_chop(fib_u, b_w+1, 1 << b_w); - _cs_jam_fib_chop(fib_u, b_w-1, a_w & ((1 << (b_w-1)) - 1)); - _cs_jam_fib_chop(fib_u, a_w, a); + { + c3_w src_w[2]; + c3_w* buf_w = fib_u->sab_u->buf_w; + + // _cs_jam_fib_chop(fib_u, b_w+1, 1 << b_w); + // + { + c3_d dat_d = (c3_d)1 << b_w; + src_w[0] = (c3_w)dat_d; + src_w[1] = dat_d >> 32; + + u3r_chop_words(0, 0, b_w + 1, bit_w, buf_w, 2, src_w); + bit_w += b_w + 1; + } + + // _cs_jam_fib_chop(fib_u, b_w-1, a_w); + // + { + src_w[0] = a_w; + u3r_chop_words(0, 0, b_w - 1, bit_w, buf_w, 1, src_w); + bit_w += b_w - 1; + } + + // _cs_jam_fib_chop(fib_u, a_w, a); + // + u3r_chop(0, 0, a_w, bit_w, buf_w, a); + } } } From b256c87f6ddf9ba42d983b39a9200e63027e5b7a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:26:10 -0400 Subject: [PATCH 02/54] jets: adds +hub --- pkg/noun/jets/c/hub.c | 61 +++++++++++++++++++++++++++++++++++++++++++ pkg/noun/jets/q.h | 1 + pkg/noun/jets/w.h | 1 + 3 files changed, 63 insertions(+) create mode 100644 pkg/noun/jets/c/hub.c diff --git a/pkg/noun/jets/c/hub.c b/pkg/noun/jets/c/hub.c new file mode 100644 index 0000000000..bae3831649 --- /dev/null +++ b/pkg/noun/jets/c/hub.c @@ -0,0 +1,61 @@ +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + +u3_noun +u3qc_hub(u3_atom a, u3_atom b) +{ + c3_w a_w, b_w, c_w; + + if ( 1 == a ) return u3k(b); + + a_w = u3r_met(0, a); + b_w = u3r_met(0, b); + + if ( b_w < a_w ) return u3m_bail(c3__exit); + + c_w = b_w - a_w; + + if ( (c3y == u3a_is_cat(a)) && (c3y == u3a_is_cat(b)) ) { + if ( a != (b >> c_w) ) return u3m_bail(c3__exit); + + return b & ((1 << c_w) - 1); + } + else { + u3_atom c, d, e, f, g; + + c = u3i_word(b_w - a_w); + d = u3qc_rsh(0, c, b); + + if ( c3n == u3r_sing(a, d) ) return u3m_bail(c3__exit); + + e = u3qc_bex(c); + f = u3qa_dec(e); + g = u3qc_dis(b, f); + + u3z(c); + u3z(d); + u3z(e); + u3z(f); + + return g; + } +} + +u3_noun +u3wc_hub(u3_noun cor) +{ + u3_noun a, b; + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) + || (0 == a) + || (0 == b) + || (c3n == u3ud(b)) + || (c3n == u3ud(a) && b != 1) ) + { + return u3m_bail(c3__exit); + } + else { + return u3qc_hub(a, b); + } +} diff --git a/pkg/noun/jets/q.h b/pkg/noun/jets/q.h index e9c8bfd9b3..ad4b10b82e 100644 --- a/pkg/noun/jets/q.h +++ b/pkg/noun/jets/q.h @@ -57,6 +57,7 @@ u3_noun u3qc_dvr(u3_atom, u3_atom); u3_noun u3qc_end(u3_atom, u3_atom, u3_atom); u3_noun u3qc_gor(u3_atom, u3_atom); + u3_noun u3qc_hub(u3_atom, u3_atom); u3_noun u3qc_lsh(u3_atom, u3_atom, u3_atom); u3_noun u3qc_mas(u3_atom); u3_noun u3qc_met(u3_atom, u3_atom); diff --git a/pkg/noun/jets/w.h b/pkg/noun/jets/w.h index 2898e0b6e6..76ff87d4be 100644 --- a/pkg/noun/jets/w.h +++ b/pkg/noun/jets/w.h @@ -58,6 +58,7 @@ u3_noun u3wc_dor(u3_noun); u3_noun u3wc_dvr(u3_noun); u3_noun u3wc_end(u3_noun); + u3_noun u3wc_hub(u3_noun); u3_noun u3wc_gor(u3_noun); u3_noun u3wc_lsh(u3_noun); u3_noun u3wc_mas(u3_noun); From af6adb8fb52cd94fa0e6061cc3611f913cf2759d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:29:00 -0400 Subject: [PATCH 03/54] jets: adds +pin --- pkg/noun/jets/c/pin.c | 54 +++++++++++++++++++++++++++++++++++++++++++ pkg/noun/jets/q.h | 1 + pkg/noun/jets/w.h | 1 + 3 files changed, 56 insertions(+) create mode 100644 pkg/noun/jets/c/pin.c diff --git a/pkg/noun/jets/c/pin.c b/pkg/noun/jets/c/pin.c new file mode 100644 index 0000000000..c1b45581f8 --- /dev/null +++ b/pkg/noun/jets/c/pin.c @@ -0,0 +1,54 @@ +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + +u3_noun +u3qc_pin(u3_atom a, u3_atom b) +{ + c3_w a_w, b_w, c_w; + + if ( 1 == a ) return c3y; + if ( 1 == b ) return c3n; + + a_w = u3r_met(0, a); + b_w = u3r_met(0, b); + + if ( b_w < a_w ) return c3n; + + c_w = b_w - a_w; + + if ( (c3y == u3a_is_cat(a)) && (c3y == u3a_is_cat(b)) ) { + return __(a == (b >> (b_w - a_w))); + } + else { + u3_atom c, d, e; + + c = u3i_word(b_w - a_w); + d = u3qc_rsh(0, c, b); + e = u3r_sing(a, d); + + u3z(c); + u3z(d); + + return e; + } +} + +u3_noun +u3wc_pin(u3_noun cor) +{ + u3_noun a, b; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) + || (0 == a) + || (0 == b) + || (c3n == u3ud(b)) + || (c3n == u3ud(a)) ) + { + return u3m_bail(c3__exit); + } + else { + return u3qc_pin(a, b); + } +} diff --git a/pkg/noun/jets/q.h b/pkg/noun/jets/q.h index ad4b10b82e..8a6cb15be7 100644 --- a/pkg/noun/jets/q.h +++ b/pkg/noun/jets/q.h @@ -65,6 +65,7 @@ u3_noun u3qc_mor(u3_atom, u3_atom); u3_noun u3qc_muk(u3_atom, u3_atom, u3_atom); u3_noun u3qc_peg(u3_atom, u3_atom); + u3_noun u3qc_pin(u3_atom, u3_atom); u3_noun u3qc_pow(u3_atom, u3_atom); u3_noun u3qc_rap(u3_atom, u3_noun); u3_noun u3qc_rep(u3_atom, u3_atom, u3_noun); diff --git a/pkg/noun/jets/w.h b/pkg/noun/jets/w.h index 76ff87d4be..df1d5c0fba 100644 --- a/pkg/noun/jets/w.h +++ b/pkg/noun/jets/w.h @@ -68,6 +68,7 @@ u3_noun u3wc_mug(u3_noun); u3_noun u3wc_muk(u3_noun); u3_noun u3wc_peg(u3_noun); + u3_noun u3wc_pin(u3_noun); u3_noun u3wc_pow(u3_noun); u3_noun u3wc_rap(u3_noun); u3_noun u3wc_rep(u3_noun); From 9d42e0dbb94a74b24b40ada50890a2938503940d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:32:13 -0400 Subject: [PATCH 04/54] jets: fixes unsafe c3_w -> atom conversion in +peg --- pkg/noun/jets/c/peg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/noun/jets/c/peg.c b/pkg/noun/jets/c/peg.c index 28a8f3b2bd..16508c11af 100644 --- a/pkg/noun/jets/c/peg.c +++ b/pkg/noun/jets/c/peg.c @@ -14,16 +14,15 @@ return u3k(a); } - u3_atom c, d, e, f, g, h; + u3_atom d, e, f, g, h; + c3_w c_w = u3r_met(0, b) - 1; - c = u3r_met(0, b); - d = u3qa_dec(c); + d = u3i_word(c_w); e = u3qc_lsh(0, d, 1); f = u3qa_sub(b, e); g = u3qc_lsh(0, d, a); h = u3qa_add(f, g); - u3z(c); u3z(d); u3z(e); u3z(f); From b1d7d26cf738e73e8a05255af216817f002f0532 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:44:48 -0400 Subject: [PATCH 05/54] jets: optimizes direct +peg --- pkg/noun/jets/c/peg.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/pkg/noun/jets/c/peg.c b/pkg/noun/jets/c/peg.c index 16508c11af..c87bff3c11 100644 --- a/pkg/noun/jets/c/peg.c +++ b/pkg/noun/jets/c/peg.c @@ -14,21 +14,29 @@ return u3k(a); } - u3_atom d, e, f, g, h; c3_w c_w = u3r_met(0, b) - 1; - d = u3i_word(c_w); - e = u3qc_lsh(0, d, 1); - f = u3qa_sub(b, e); - g = u3qc_lsh(0, d, a); - h = u3qa_add(f, g); + if ( (c3y == u3a_is_cat(a) && (c3y == u3a_is_cat(b))) ) { + c3_w d_w = b - (1 << c_w); + c3_d e_d = (c3_d)a << c_w; + return u3i_chub(d_w + e_d); + } + else { + u3_atom d, e, f, g, h; + + d = u3i_word(c_w); + e = u3qc_lsh(0, d, 1); + f = u3qa_sub(b, e); + g = u3qc_lsh(0, d, a); + h = u3qa_add(f, g); - u3z(d); - u3z(e); - u3z(f); - u3z(g); + u3z(d); + u3z(e); + u3z(f); + u3z(g); - return h; + return h; + } } u3_noun u3wc_peg(u3_noun cor) From 8fea31ec12657167fcb31a3201787deaeab1ca42 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:45:13 -0400 Subject: [PATCH 06/54] jets: restyles +peg --- pkg/noun/jets/c/peg.c | 93 +++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/pkg/noun/jets/c/peg.c b/pkg/noun/jets/c/peg.c index c87bff3c11..cc39a1022b 100644 --- a/pkg/noun/jets/c/peg.c +++ b/pkg/noun/jets/c/peg.c @@ -1,57 +1,54 @@ -/// @file - #include "jets/q.h" #include "jets/w.h" #include "noun.h" +u3_noun +u3qc_peg(u3_atom a, u3_atom b) +{ + if ( 1 == b ) { + return u3k(a); + } - u3_noun - u3qc_peg(u3_atom a, - u3_atom b) - { - if ( 1 == b ) { - return u3k(a); - } - - c3_w c_w = u3r_met(0, b) - 1; - - if ( (c3y == u3a_is_cat(a) && (c3y == u3a_is_cat(b))) ) { - c3_w d_w = b - (1 << c_w); - c3_d e_d = (c3_d)a << c_w; - return u3i_chub(d_w + e_d); - } - else { - u3_atom d, e, f, g, h; - - d = u3i_word(c_w); - e = u3qc_lsh(0, d, 1); - f = u3qa_sub(b, e); - g = u3qc_lsh(0, d, a); - h = u3qa_add(f, g); - - u3z(d); - u3z(e); - u3z(f); - u3z(g); - - return h; - } + c3_w c_w = u3r_met(0, b) - 1; + + if ( (c3y == u3a_is_cat(a) && (c3y == u3a_is_cat(b))) ) { + c3_w d_w = b - (1 << c_w); + c3_d e_d = (c3_d)a << c_w; + return u3i_chub(d_w + e_d); + } + else { + u3_atom d, e, f, g, h; + + d = u3i_word(c_w); + e = u3qc_lsh(0, d, 1); + f = u3qa_sub(b, e); + g = u3qc_lsh(0, d, a); + h = u3qa_add(f, g); + + u3z(d); + u3z(e); + u3z(f); + u3z(g); + + return h; } - u3_noun - u3wc_peg(u3_noun cor) +} + +u3_noun +u3wc_peg(u3_noun cor) +{ + u3_noun a, b; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) || + (0 == a) || + (0 == b) || + (c3n == u3ud(b)) || + (c3n == u3ud(a) && b != 1) ) { - u3_noun a, b; - - if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) || - (0 == a) || - (0 == b) || - (c3n == u3ud(b)) || - (c3n == u3ud(a) && b != 1) ) - { - return u3m_bail(c3__exit); - } else { - return u3qc_peg(a, b); - } + return u3m_bail(c3__exit); } - + else { + return u3qc_peg(a, b); + } +} From 30279b8990d2c87a7f1664e74b1d8c33a91af045 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:43:39 -0400 Subject: [PATCH 07/54] jets: fixes unsafe c3_w -> atom conversion in +mas --- pkg/noun/jets/c/mas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/jets/c/mas.c b/pkg/noun/jets/c/mas.c index 7b2658d738..881ae73977 100644 --- a/pkg/noun/jets/c/mas.c +++ b/pkg/noun/jets/c/mas.c @@ -17,8 +17,8 @@ return u3m_bail(c3__exit); } else { - c = u3qc_bex((b_w - 1)); - d = u3qc_bex((b_w - 2)); + c = u3qc_bex(u3i_word(b_w - 1)); + d = u3qc_bex(u3i_word(b_w - 2)); e = u3qa_sub(a, c); f = u3qc_con(e, d); From 76ce8392ba8032c2f7efc6ecb89d2ebea78d82d3 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:44:08 -0400 Subject: [PATCH 08/54] jets: optimizes direct +mas --- pkg/noun/jets/c/mas.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/noun/jets/c/mas.c b/pkg/noun/jets/c/mas.c index 881ae73977..63c8632079 100644 --- a/pkg/noun/jets/c/mas.c +++ b/pkg/noun/jets/c/mas.c @@ -16,6 +16,9 @@ if ( b_w < 2 ) { return u3m_bail(c3__exit); } + else if ( c3y == u3a_is_cat(a) ) { + return (a - (1 << (b_w - 1))) | (1 << (b_w - 2)); + } else { c = u3qc_bex(u3i_word(b_w - 1)); d = u3qc_bex(u3i_word(b_w - 2)); From 0b114c5c2c151daa6faa8c88a07806510ddf2252 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 16 May 2023 23:45:48 -0400 Subject: [PATCH 09/54] jets: restyles +mas --- pkg/noun/jets/c/mas.c | 72 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/pkg/noun/jets/c/mas.c b/pkg/noun/jets/c/mas.c index 63c8632079..4d5f0e45ca 100644 --- a/pkg/noun/jets/c/mas.c +++ b/pkg/noun/jets/c/mas.c @@ -1,48 +1,46 @@ -/// @file - #include "jets/q.h" #include "jets/w.h" #include "noun.h" +u3_noun +u3qc_mas(u3_atom a) +{ + c3_w b_w; + u3_atom c, d, e, f; - u3_noun - u3qc_mas(u3_atom a) - { - c3_w b_w; - u3_atom c, d, e, f; - - b_w = u3r_met(0, a); - if ( b_w < 2 ) { - return u3m_bail(c3__exit); - } - else if ( c3y == u3a_is_cat(a) ) { - return (a - (1 << (b_w - 1))) | (1 << (b_w - 2)); - } - else { - c = u3qc_bex(u3i_word(b_w - 1)); - d = u3qc_bex(u3i_word(b_w - 2)); - e = u3qa_sub(a, c); - f = u3qc_con(e, d); + b_w = u3r_met(0, a); + if ( b_w < 2 ) { + return u3m_bail(c3__exit); + } + else if ( c3y == u3a_is_cat(a) ) { + return (a - (1 << (b_w - 1))) | (1 << (b_w - 2)); + } + else { + c = u3qc_bex(u3i_word(b_w - 1)); + d = u3qc_bex(u3i_word(b_w - 2)); + e = u3qa_sub(a, c); + f = u3qc_con(e, d); - u3z(c); - u3z(d); - u3z(e); + u3z(c); + u3z(d); + u3z(e); - return f; - } + return f; } - u3_noun - u3wc_mas(u3_noun cor) - { - u3_noun a; +} - if ( (u3_none == (a = u3r_at(u3x_sam, cor))) || - (c3n == u3ud(a)) ) - { - return u3m_bail(c3__exit); - } else { - return u3qc_mas(a); - } - } +u3_noun +u3wc_mas(u3_noun cor) +{ + u3_noun a; + if ( (u3_none == (a = u3r_at(u3x_sam, cor))) || + (c3n == u3ud(a)) ) + { + return u3m_bail(c3__exit); + } + else { + return u3qc_mas(a); + } +} From 2f4c64ebc72d4d7dd8211a8e446b5508742d72ad Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 17 May 2023 10:58:13 -0400 Subject: [PATCH 10/54] jets: remove redundant expressions in +pin and +hub --- pkg/noun/jets/c/hub.c | 2 +- pkg/noun/jets/c/pin.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/noun/jets/c/hub.c b/pkg/noun/jets/c/hub.c index bae3831649..c4bf6e4726 100644 --- a/pkg/noun/jets/c/hub.c +++ b/pkg/noun/jets/c/hub.c @@ -25,7 +25,7 @@ u3qc_hub(u3_atom a, u3_atom b) else { u3_atom c, d, e, f, g; - c = u3i_word(b_w - a_w); + c = u3i_word(c_w); d = u3qc_rsh(0, c, b); if ( c3n == u3r_sing(a, d) ) return u3m_bail(c3__exit); diff --git a/pkg/noun/jets/c/pin.c b/pkg/noun/jets/c/pin.c index c1b45581f8..33d608f096 100644 --- a/pkg/noun/jets/c/pin.c +++ b/pkg/noun/jets/c/pin.c @@ -19,12 +19,12 @@ u3qc_pin(u3_atom a, u3_atom b) c_w = b_w - a_w; if ( (c3y == u3a_is_cat(a)) && (c3y == u3a_is_cat(b)) ) { - return __(a == (b >> (b_w - a_w))); + return __(a == (b >> c_w)); } else { u3_atom c, d, e; - c = u3i_word(b_w - a_w); + c = u3i_word(c_w); d = u3qc_rsh(0, c, b); e = u3r_sing(a, d); From e1adbfbae9cf6610f279dae680a3be9771dafa91 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 17 May 2023 10:59:28 -0400 Subject: [PATCH 11/54] jets: corrects axis math in +hub --- pkg/noun/jets/c/hub.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/noun/jets/c/hub.c b/pkg/noun/jets/c/hub.c index c4bf6e4726..80214754d7 100644 --- a/pkg/noun/jets/c/hub.c +++ b/pkg/noun/jets/c/hub.c @@ -18,12 +18,16 @@ u3qc_hub(u3_atom a, u3_atom b) c_w = b_w - a_w; if ( (c3y == u3a_is_cat(a)) && (c3y == u3a_is_cat(b)) ) { + c3_w d_w; + if ( a != (b >> c_w) ) return u3m_bail(c3__exit); - return b & ((1 << c_w) - 1); + d_w = 1 << c_w; + + return (b & (d_w - 1)) | d_w; } else { - u3_atom c, d, e, f, g; + u3_atom c, d, e, f, g, h; c = u3i_word(c_w); d = u3qc_rsh(0, c, b); @@ -33,13 +37,15 @@ u3qc_hub(u3_atom a, u3_atom b) e = u3qc_bex(c); f = u3qa_dec(e); g = u3qc_dis(b, f); + h = u3qc_con(g, e); u3z(c); u3z(d); u3z(e); u3z(f); + u3z(g); - return g; + return h; } } From 259cda50e2a617fbdc27f75e188a27354c437837 Mon Sep 17 00:00:00 2001 From: Alex Shelkovnykov Date: Sun, 4 Jun 2023 13:38:11 +0000 Subject: [PATCH 12/54] jets: match hoon changes to bif:by --- pkg/noun/jets/d/by_bif.c | 6 ++---- pkg/noun/jets/d/by_dif.c | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/noun/jets/d/by_bif.c b/pkg/noun/jets/d/by_bif.c index d9e27d1756..0a2f23a666 100644 --- a/pkg/noun/jets/d/by_bif.c +++ b/pkg/noun/jets/d/by_bif.c @@ -17,19 +17,17 @@ _b_bif_putroot(u3_noun a, else { u3_noun n_a, l_a, r_a; u3_noun p_n_a, q_n_a; - u3_noun p_b, q_b; u3x_trel(a, &n_a, &l_a, &r_a); - u3x_cell(b, &p_b, &q_b); u3x_cell(n_a, &p_n_a, &q_n_a); - if ( c3y == u3r_sing(p_b, p_n_a) ) { + if ( c3y == u3r_sing(b, p_n_a) ) { return u3nt(u3k(b), u3k(l_a), u3k(r_a)); } else { u3_noun c, n_c, l_c, r_c; u3_noun d; - if ( c3y == u3qc_gor(p_b, p_n_a) ) { + if ( c3y == u3qc_gor(b, p_n_a) ) { c = _b_bif_putroot(l_a, b); u3r_trel(c, &n_c, &l_c, &r_c); d = u3nt(u3k(n_c), diff --git a/pkg/noun/jets/d/by_dif.c b/pkg/noun/jets/d/by_dif.c index a3f35f3cde..44dcd1ad1b 100644 --- a/pkg/noun/jets/d/by_dif.c +++ b/pkg/noun/jets/d/by_dif.c @@ -61,11 +61,12 @@ u3qdb_dif(u3_noun a, return u3k(a); } else { - u3_noun n_b, l_b, r_b; + u3_noun n_b, p_n_b, q_n_b, l_b, r_b; u3_noun c, l_c, r_c; u3x_trel(b, &n_b, &l_b, &r_b); + u3x_cell(n_b, &p_n_b, &q_n_b); - c = u3qdb_bif(a, n_b); + c = u3qdb_bif(a, p_n_b); u3x_cell(c, &l_c, &r_c); u3_noun d = u3qdb_dif(l_c, l_b); From 563a0c24a48870db0b08e19a11dcce7c51a9b8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Paraniak?= Date: Thu, 8 Jun 2023 10:00:50 +0800 Subject: [PATCH 13/54] jets: fixes indentation in +fitz jet --- pkg/noun/jets/f/fitz.c | 90 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/pkg/noun/jets/f/fitz.c b/pkg/noun/jets/f/fitz.c index f8cff2b1c9..a08fd91871 100644 --- a/pkg/noun/jets/f/fitz.c +++ b/pkg/noun/jets/f/fitz.c @@ -6,62 +6,62 @@ #include "noun.h" - static u3_noun - _fitz_fiz(u3_noun yaz, - u3_noun wix) - { - c3_w yaz_w = u3r_met(3, yaz); - c3_w wix_w = u3r_met(3, wix); - c3_y yaz_y, wix_y; +static u3_noun +_fitz_fiz(u3_noun yaz, + u3_noun wix) +{ + c3_w yaz_w = u3r_met(3, yaz); + c3_w wix_w = u3r_met(3, wix); + c3_y yaz_y, wix_y; - yaz_y = (0 == yaz_w) ? 0 : u3r_byte((yaz_w - 1), yaz); - if ( (yaz_y < 'A') || (yaz_y > 'Z') ) yaz_y = 0; + yaz_y = (0 == yaz_w) ? 0 : u3r_byte((yaz_w - 1), yaz); + if ( (yaz_y < 'A') || (yaz_y > 'Z') ) yaz_y = 0; - wix_y = (0 == wix_w) ? 0 : u3r_byte((wix_w - 1), wix); - if ( (wix_y < 'A') || (wix_y > 'Z') ) wix_y = 0; + wix_y = (0 == wix_w) ? 0 : u3r_byte((wix_w - 1), wix); + if ( (wix_y < 'A') || (wix_y > 'Z') ) wix_y = 0; - if ( yaz_y && wix_y ) { - if ( !wix_y || (wix_y > yaz_y) ) { - return c3n; - } + if ( yaz_y && wix_y ) { + if ( !wix_y || (wix_y > yaz_y) ) { + return c3n; } - return c3y; } + return c3y; +} - u3_noun - u3qf_fitz(u3_noun yaz, - u3_noun wix) - { - c3_w i_w, met_w = c3_min(u3r_met(3, yaz), u3r_met(3, wix)); +u3_noun +u3qf_fitz(u3_noun yaz, + u3_noun wix) +{ + c3_w i_w, met_w = c3_min(u3r_met(3, yaz), u3r_met(3, wix)); - if ( c3n == _fitz_fiz(yaz, wix) ) { - return c3n; - } - for ( i_w = 0; i_w < met_w; i_w++ ) { - c3_y yaz_y = u3r_byte(i_w, yaz); - c3_y wix_y = u3r_byte(i_w, wix); + if ( c3n == _fitz_fiz(yaz, wix) ) { + return c3n; + } + for ( i_w = 0; i_w < met_w; i_w++ ) { + c3_y yaz_y = u3r_byte(i_w, yaz); + c3_y wix_y = u3r_byte(i_w, wix); - if ( (yaz_y >= 'A') && (yaz_y <= 'Z') ) yaz_y = 0; - if ( (wix_y >= 'A') && (wix_y <= 'Z') ) wix_y = 0; + if ( (yaz_y >= 'A') && (yaz_y <= 'Z') ) yaz_y = 0; + if ( (wix_y >= 'A') && (wix_y <= 'Z') ) wix_y = 0; - if ( yaz_y && wix_y && (yaz_y != wix_y) ) { - return c3n; - } + if ( yaz_y && wix_y && (yaz_y != wix_y) ) { + return c3n; } - return c3y; } + return c3y; +} - u3_noun - u3wf_fitz(u3_noun cor) - { - u3_noun yaz, wix; +u3_noun +u3wf_fitz(u3_noun cor) +{ + u3_noun yaz, wix; - if ( (c3n == u3r_mean(cor, u3x_sam_2, &yaz, u3x_sam_3, &wix, 0)) || - (c3n == u3ud(yaz)) || - (c3n == u3ud(wix)) ) - { - return u3m_bail(c3__fail); - } else { - return u3qf_fitz(yaz, wix); - } + if ( (c3n == u3r_mean(cor, u3x_sam_2, &yaz, u3x_sam_3, &wix, 0)) || + (c3n == u3ud(yaz)) || + (c3n == u3ud(wix)) ) + { + return u3m_bail(c3__fail); + } else { + return u3qf_fitz(yaz, wix); } +} From 88cc266f5710a6690c42c35366f313e0cb216908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Paraniak?= Date: Thu, 8 Jun 2023 10:41:44 +0800 Subject: [PATCH 14/54] jets: fix a jet mismatch in +fitz The +fitz jet erronously excludes all uppercase letters but the last one from aura compatibility check. In +fitz aura compatibility check, only the last uppercase letter is considered a bit-width annotation. --- pkg/noun/jets/f/fitz.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pkg/noun/jets/f/fitz.c b/pkg/noun/jets/f/fitz.c index a08fd91871..b1c2a5dfb3 100644 --- a/pkg/noun/jets/f/fitz.c +++ b/pkg/noun/jets/f/fitz.c @@ -5,7 +5,6 @@ #include "noun.h" - static u3_noun _fitz_fiz(u3_noun yaz, u3_noun wix) @@ -21,10 +20,11 @@ _fitz_fiz(u3_noun yaz, if ( (wix_y < 'A') || (wix_y > 'Z') ) wix_y = 0; if ( yaz_y && wix_y ) { - if ( !wix_y || (wix_y > yaz_y) ) { + if ( wix_y > yaz_y ) { return c3n; } } + return c3y; } @@ -32,7 +32,10 @@ u3_noun u3qf_fitz(u3_noun yaz, u3_noun wix) { - c3_w i_w, met_w = c3_min(u3r_met(3, yaz), u3r_met(3, wix)); + c3_w yet_w = u3r_met(3, yaz); + c3_w wet_w = u3r_met(3, wix); + + c3_w i_w, met_w = c3_min(yet_w, wet_w); if ( c3n == _fitz_fiz(yaz, wix) ) { return c3n; @@ -41,10 +44,15 @@ u3qf_fitz(u3_noun yaz, c3_y yaz_y = u3r_byte(i_w, yaz); c3_y wix_y = u3r_byte(i_w, wix); - if ( (yaz_y >= 'A') && (yaz_y <= 'Z') ) yaz_y = 0; - if ( (wix_y >= 'A') && (wix_y <= 'Z') ) wix_y = 0; + if ( (i_w == (yet_w - 1)) && (yaz_y >= 'A') && (yaz_y <= 'Z')) { + return c3y; + } + + if ( (i_w == (wet_w - 1)) && (wix_y >= 'A') && (wix_y <= 'Z')) { + return c3y; + } - if ( yaz_y && wix_y && (yaz_y != wix_y) ) { + if ( yaz_y != wix_y ) { return c3n; } } From 1af03ee813fe2068b6e68b56590a280dbe0fa3c2 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 20 Jun 2023 18:37:39 -0400 Subject: [PATCH 15/54] vere: bumps hoon kelvin to %138 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 6f21269063..ebe4befd08 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -813,7 +813,7 @@ _pier_wyrd_card(u3_pier* pir_u) u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX from both king and serf? u3nc(c3__lull, VERE_LULL), // XX from both king and serf? u3nc(c3__arvo, 237), // XX from both king and serf? - u3nc(c3__hoon, 139), // god_u->hon_y + u3nc(c3__hoon, 138), // god_u->hon_y u3nc(c3__nock, 4), // god_u->noc_y u3_none); u3_noun wir = u3nc(c3__arvo, u3_nul); From d1661045fe7b77cb9041d66e33528657f855ea34 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 1 Aug 2023 12:09:44 -0400 Subject: [PATCH 16/54] vere: bump %lull kelvin to %322 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 1e39d14ef4..506a59a195 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -676,7 +676,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // #define VERE_NAME "vere" #define VERE_ZUSE 412 -#define VERE_LULL 323 +#define VERE_LULL 322 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ From f06846d29daac1564a925355dae897853d68ea27 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 1 Aug 2023 12:10:18 -0400 Subject: [PATCH 17/54] vere: decrement zuse to %411 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 506a59a195..8e54dbb37e 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -675,7 +675,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 412 +#define VERE_ZUSE 411 #define VERE_LULL 322 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN From 6ad0148f56b6208c147e8ea7f351ff3e71dead3d Mon Sep 17 00:00:00 2001 From: Pyry Kovanen Date: Wed, 23 Aug 2023 23:05:34 +0300 Subject: [PATCH 18/54] pier: decrement arvo kelvin --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 8e54dbb37e..6bd0384d43 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -814,7 +814,7 @@ _pier_wyrd_card(u3_pier* pir_u) u3_nul); u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX from both king and serf? u3nc(c3__lull, VERE_LULL), // XX from both king and serf? - u3nc(c3__arvo, 237), // XX from both king and serf? + u3nc(c3__arvo, 236), // XX from both king and serf? u3nc(c3__hoon, 139), // god_u->hon_y u3nc(c3__nock, 4), // god_u->noc_y u3_none); From 94d4bb0b49bf699bc9965becaacfb9d861ef74f6 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Sat, 19 Aug 2023 18:20:13 -0400 Subject: [PATCH 19/54] build: upgrade `zlib` to v1.3 --- WORKSPACE.bazel | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 56a347ed6d..2cad948ace 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -358,10 +358,10 @@ versioned_http_archive( versioned_http_archive( name = "zlib", build_file = "//bazel/third_party/zlib:zlib.BUILD", - sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", + sha256 = "ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e", strip_prefix = "zlib-{version}", url = "https://www.zlib.net/zlib-{version}.tar.gz", - version = "1.2.13", + version = "1.3", ) # From 3a06580796def107bfa66a52f1b4e450f240d7fe Mon Sep 17 00:00:00 2001 From: Sidnym Ladrut Date: Mon, 4 Sep 2023 23:36:43 +0000 Subject: [PATCH 20/54] add 'mate' jet --- pkg/noun/jets/b/mate.c | 30 ++++++++++++++++++++++++++++++ pkg/noun/jets/q.h | 2 ++ pkg/noun/jets/tree.c | 3 +++ pkg/noun/jets/w.h | 2 ++ 4 files changed, 37 insertions(+) create mode 100644 pkg/noun/jets/b/mate.c diff --git a/pkg/noun/jets/b/mate.c b/pkg/noun/jets/b/mate.c new file mode 100644 index 0000000000..77e4fbb819 --- /dev/null +++ b/pkg/noun/jets/b/mate.c @@ -0,0 +1,30 @@ +/// @file + +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + + + u3_noun + u3qb_mate(u3_noun a, + u3_noun b) + { + if ( u3_nul == b ) { + return u3k(a); + } else if ( u3_nul == a ) { + return u3k(b); + } else if ( c3y == u3r_sing(a, b) ) { + return u3k(a); + } else { + return u3m_bail(c3__fail); + } + } + u3_noun + u3wb_mate(u3_noun cor) + { + u3_noun a, b; + u3x_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0); + return u3qb_mate(a, b); + } + diff --git a/pkg/noun/jets/q.h b/pkg/noun/jets/q.h index 33c63ef42b..8a7c398c3c 100644 --- a/pkg/noun/jets/q.h +++ b/pkg/noun/jets/q.h @@ -32,6 +32,7 @@ u3_noun u3qb_lien(u3_noun, u3_noun); u3_noun u3qb_murn(u3_noun, u3_noun); u3_noun u3qb_need(u3_noun); + u3_noun u3qb_mate(u3_noun, u3_noun); u3_noun u3qb_reap(u3_atom, u3_noun); u3_noun u3qb_reel(u3_noun, u3_noun); u3_noun u3qb_roll(u3_noun, u3_noun); @@ -254,3 +255,4 @@ void u3qf_test(const c3_c*, u3_noun); #endif /* ifndef U3_JETS_Q_H */ + diff --git a/pkg/noun/jets/tree.c b/pkg/noun/jets/tree.c index c15e29ba8e..e2ce880293 100644 --- a/pkg/noun/jets/tree.c +++ b/pkg/noun/jets/tree.c @@ -2139,6 +2139,7 @@ static c3_c* _k140_ha[] = { /* new jets */ + static u3j_harm _139_two_mate_a[] = {{".2", u3wb_mate, c3y}, {}}; static u3j_harm _139_hex_json_de_a[] = {{".2", u3we_json_de}, {}}; static u3j_harm _139_hex_json_en_a[] = {{".2", u3we_json_en}, {}}; static u3j_core _139_hex_json_d[] = @@ -2282,6 +2283,7 @@ static u3j_core _139_two_d[] = { "lien", 7, _140_two_lien_a, 0, no_hashes }, { "murn", 7, _140_two_murn_a, 0, no_hashes }, { "need", 7, _140_two_need_a, 0, no_hashes }, + { "mate", 7, _139_two_mate_a, 0, no_hashes }, { "reap", 7, _140_two_reap_a, 0, no_hashes }, { "reel", 7, _140_two_reel_a, 0, no_hashes }, { "roll", 7, _140_two_roll_a, 0, no_hashes }, @@ -2438,3 +2440,4 @@ u3j_Dash = { 0, 0 }; + diff --git a/pkg/noun/jets/w.h b/pkg/noun/jets/w.h index d838416c03..8b9873c684 100644 --- a/pkg/noun/jets/w.h +++ b/pkg/noun/jets/w.h @@ -32,6 +32,7 @@ u3_noun u3wb_lien(u3_noun); u3_noun u3wb_murn(u3_noun); u3_noun u3wb_need(u3_noun); + u3_noun u3wb_mate(u3_noun); u3_noun u3wb_reap(u3_noun); u3_noun u3wb_reel(u3_noun); u3_noun u3wb_roll(u3_noun); @@ -332,3 +333,4 @@ u3_noun u3wfu_rest(u3_noun); #endif /* ifndef U3_JETS_W_H */ + From fb332c070728e17fc5fcb64355295766d2982213 Mon Sep 17 00:00:00 2001 From: Sidnym Ladrut Date: Wed, 6 Sep 2023 16:33:20 +0000 Subject: [PATCH 21/54] add fixes propsed by ~master-morzod --- pkg/noun/jets/b/mate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/jets/b/mate.c b/pkg/noun/jets/b/mate.c index 77e4fbb819..f8dbd31654 100644 --- a/pkg/noun/jets/b/mate.c +++ b/pkg/noun/jets/b/mate.c @@ -14,10 +14,10 @@ return u3k(a); } else if ( u3_nul == a ) { return u3k(b); - } else if ( c3y == u3r_sing(a, b) ) { + } else if ( c3y == u3r_sing(u3t(a), u3t(b)) ) { return u3k(a); } else { - return u3m_bail(c3__fail); + return u3m_error("mate"); } } u3_noun From 0335f048f857c5064c35237b552561bac932c290 Mon Sep 17 00:00:00 2001 From: Sidnym Ladrut Date: Sun, 17 Sep 2023 19:39:13 +0000 Subject: [PATCH 22/54] add fixes proposed by ~finmep-lanteb --- pkg/noun/jets/tree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/noun/jets/tree.c b/pkg/noun/jets/tree.c index e2ce880293..03c7b64e48 100644 --- a/pkg/noun/jets/tree.c +++ b/pkg/noun/jets/tree.c @@ -2139,7 +2139,6 @@ static c3_c* _k140_ha[] = { /* new jets */ - static u3j_harm _139_two_mate_a[] = {{".2", u3wb_mate, c3y}, {}}; static u3j_harm _139_hex_json_de_a[] = {{".2", u3we_json_de}, {}}; static u3j_harm _139_hex_json_en_a[] = {{".2", u3we_json_en}, {}}; static u3j_core _139_hex_json_d[] = @@ -2273,6 +2272,8 @@ static u3j_core _139_two__in_d[] = {} }; +static u3j_harm _139_two_mate_a[] = {{".2", u3wb_mate, c3y}, {}}; + static u3j_core _139_two_d[] = { { "tri", 3, 0, _139_tri_d, no_hashes, _140_tri_ho }, From 849cdc3751e675fcf824df3f49328e85ab0953be Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 26 Sep 2023 21:21:19 -0400 Subject: [PATCH 23/54] build: fetch `urcrypt` instead of vendoring it --- .github/workflows/shared.yml | 5 +- README.md | 2 - WORKSPACE.bazel | 50 +--- bazel/BUILD.bazel | 3 +- bazel/third_party/urcrypt/BUILD.bazel | 0 bazel/third_party/urcrypt/urcrypt.BUILD | 28 ++ pkg/noun/BUILD.bazel | 2 +- pkg/noun/jets.c | 2 +- pkg/noun/manage.c | 2 +- pkg/urcrypt/.gitignore | 56 ---- pkg/urcrypt/BUILD.bazel | 36 --- pkg/urcrypt/README.md | 33 --- pkg/urcrypt/aes_cbc.c | 181 ------------- pkg/urcrypt/aes_ecb.c | 111 -------- pkg/urcrypt/aes_siv.c | 181 ------------- pkg/urcrypt/argon.c | 120 --------- pkg/urcrypt/argon2/argon2-specs.pdf | Bin 459608 -> 0 bytes pkg/urcrypt/argon2/latex/pics/argon2-par.pdf | Bin 76165 -> 0 bytes pkg/urcrypt/argon2/latex/pics/compression.pdf | Bin 40828 -> 0 bytes pkg/urcrypt/argon2/latex/pics/generic.pdf | Bin 30736 -> 0 bytes .../argon2/latex/pics/power-distribution.jpg | Bin 25673 -> 0 bytes pkg/urcrypt/ed25519.c | 53 ---- pkg/urcrypt/ge-additions/BUILD.bazel | 11 - pkg/urcrypt/ge-additions/LICENSE | 27 -- pkg/urcrypt/ge-additions/README.md | 20 -- pkg/urcrypt/ge-additions/ge-additions.c | 169 ------------ pkg/urcrypt/ge-additions/ge-additions.h | 8 - pkg/urcrypt/ge_additions.c | 126 --------- pkg/urcrypt/keccak.c | 21 -- pkg/urcrypt/ripemd.c | 20 -- pkg/urcrypt/scrypt.c | 31 --- pkg/urcrypt/secp256k1.c | 245 ----------------- pkg/urcrypt/sha.c | 49 ---- pkg/urcrypt/urcrypt.h | 246 ------------------ pkg/urcrypt/util.c | 14 - pkg/urcrypt/util.h | 6 - 36 files changed, 44 insertions(+), 1814 deletions(-) create mode 100644 bazel/third_party/urcrypt/BUILD.bazel create mode 100644 bazel/third_party/urcrypt/urcrypt.BUILD delete mode 100644 pkg/urcrypt/.gitignore delete mode 100644 pkg/urcrypt/BUILD.bazel delete mode 100644 pkg/urcrypt/README.md delete mode 100644 pkg/urcrypt/aes_cbc.c delete mode 100644 pkg/urcrypt/aes_ecb.c delete mode 100644 pkg/urcrypt/aes_siv.c delete mode 100644 pkg/urcrypt/argon.c delete mode 100644 pkg/urcrypt/argon2/argon2-specs.pdf delete mode 100644 pkg/urcrypt/argon2/latex/pics/argon2-par.pdf delete mode 100644 pkg/urcrypt/argon2/latex/pics/compression.pdf delete mode 100644 pkg/urcrypt/argon2/latex/pics/generic.pdf delete mode 100644 pkg/urcrypt/argon2/latex/pics/power-distribution.jpg delete mode 100644 pkg/urcrypt/ed25519.c delete mode 100644 pkg/urcrypt/ge-additions/BUILD.bazel delete mode 100644 pkg/urcrypt/ge-additions/LICENSE delete mode 100644 pkg/urcrypt/ge-additions/README.md delete mode 100644 pkg/urcrypt/ge-additions/ge-additions.c delete mode 100644 pkg/urcrypt/ge-additions/ge-additions.h delete mode 100644 pkg/urcrypt/ge_additions.c delete mode 100644 pkg/urcrypt/keccak.c delete mode 100644 pkg/urcrypt/ripemd.c delete mode 100644 pkg/urcrypt/scrypt.c delete mode 100644 pkg/urcrypt/secp256k1.c delete mode 100644 pkg/urcrypt/sha.c delete mode 100644 pkg/urcrypt/urcrypt.h delete mode 100644 pkg/urcrypt/util.c delete mode 100644 pkg/urcrypt/util.h diff --git a/.github/workflows/shared.yml b/.github/workflows/shared.yml index eec7f3fec9..d2f4959d0c 100644 --- a/.github/workflows/shared.yml +++ b/.github/workflows/shared.yml @@ -43,7 +43,7 @@ jobs: # runner with BuildJet instead. - { target: linux-aarch64, runner: buildjet-2vcpu-ubuntu-2204-arm } - { target: linux-x86_64, runner: ubuntu-22.04 } - # GitHub doesn't provide macOS machines with Apple Silicon, so we + # GitHub doesn't provide macOS machines with Apple Silicon, so we # self-host a runner with MacStadium instead. - { target: macos-aarch64, runner: [self-hosted, macos, ARM64] } - { target: macos-x86_64, runner: macos-12 } @@ -72,7 +72,7 @@ jobs: /private/var/tmp/_bazel_$(whoami) # Cache musl libc toolchains. /usr/local/*-musl - + - name: chown /usr/local/*-musl if: ${{ matrix.target == 'linux-x86_64' || matrix.target == 'linux-aarch64'}} run: | @@ -119,6 +119,7 @@ jobs: bazel run //bazel/toolchain:x86_64-linux-musl-gcc ;; "macos-aarch64") + brew install pkg-config ;; "macos-x86_64") # Switch Xcode path to match the path specified in our bazel toolchain. diff --git a/README.md b/README.md index 9e68fafdad..679d829fac 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,6 @@ defined in its own package: - [`pkg/c3`](pkg/c3): A set of basic utilities for writing Urbit's style of C. - [`pkg/ent`](pkg/ent): A cross-platform wrapper for `getentropy(2)`. -- [`pkg/urcrypt`](pkg/urcrypt): A standardized interface for calling various - cryptographic functions used in the Urbit runtime. - [`pkg/ur`](pkg/ur): An implementation of [jam][jam] and [cue][cue], Urbit's bitwise noun serialization and deserialization algorithms, respectively. - [`pkg/noun`](pkg/noun): The Nock virtual machine and snapshotting system. diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 2cad948ace..c5a66ad095 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -121,15 +121,6 @@ versioned_http_archive( version = "9681279cfaa6e6399bb7ca3afbbc27fc2e19df4b", ) -versioned_http_archive( - name = "argon2", - build_file = "//bazel/third_party/argon2:argon2.BUILD", - sha256 = "40850e6e6324be10f14228d17b617ad2074bb926eeddd6fe40ad5df833833949", - strip_prefix = "argon2-{version}", - url = "https://github.com/urbit/argon2/archive/{version}.tar.gz", - version = "a4c1e3f7138c2e577376beb99f964cf71e1c8b1b", -) - versioned_http_archive( name = "bazel_gazelle", sha256 = "efbbba6ac1a4fd342d5122cbdfdb82aeb2cf2862e35022c752eaddffada7c3f3", @@ -154,15 +145,6 @@ versioned_http_archive( version = "7.85.0", ) -versioned_http_archive( - name = "ed25519", - build_file = "//bazel/third_party/ed25519:ed25519.BUILD", - sha256 = "373923c85f61276e3cad2c0ae7a5d5cd4809ffe46c5abc1dc8276683a55782a0", - strip_prefix = "ed25519-{version}", - url = "https://github.com/orlp/ed25519/archive/{version}.tar.gz", - version = "7fa6712ef5d581a6981ec2b08ee623314cd1d1c4", -) - versioned_http_archive( name = "gmp", build_file = "//bazel/third_party/gmp:gmp.BUILD", @@ -214,17 +196,6 @@ versioned_http_file( version = "255fb1ca8206072f1d09425f0db61ecfe7ff5b17", ) -versioned_http_archive( - name = "keccak_tiny", - build_file = "//bazel/third_party/keccak_tiny:keccak_tiny.BUILD", - patch_args = ["-p1"], - patches = ["//bazel/third_party/keccak_tiny:{version}.patch"], - sha256 = "6d4717f96b84805886c74bad89e911076664d992f197634fd7cdfca2ac0f62ef", - strip_prefix = "keccak-tiny-{version}", - url = "https://github.com/coruus/keccak-tiny/archive/{version}.tar.gz", - version = "64b6647514212b76ae7bca0dea9b7b197d1d8186", -) - versioned_http_archive( name = "lmdb", build_file = "//bazel/third_party/lmdb:lmdb.BUILD", @@ -272,18 +243,6 @@ versioned_http_archive( version = "67108d883061043e55d0fb13961ac1b6fc8a485c", ) -versioned_http_archive( - name = "scrypt", - build_file = "//bazel/third_party/scrypt:scrypt.BUILD", - sha256 = "df681fb19b653b1a12970ebb6091bb2b58411b9e7baf01143870f6be3f099541", - strip_prefix = "libscrypt-{version}", - url = "https://github.com/technion/libscrypt/archive/{version}.tar.gz", - # When bumping the version, compare `Makefile` in the `scrypt` repo to - # {build_file} and confirm that {build_file} remains an accurate description - # of the scrypt build process. - version = "60e585cdd752262b22ed4113eca41c0461a61608", -) - versioned_http_archive( name = "secp256k1", build_file = "//bazel/third_party/secp256k1:secp256k1.BUILD", @@ -337,6 +296,15 @@ versioned_http_file( version = "ea8fee3aa0434d4bdf1bf785e5ec346c7ecba7fd", ) +versioned_http_archive( + name = "urcrypt", + build_file = "//bazel/third_party/urcrypt:urcrypt.BUILD", + sha256 = "00ec597c14c418802d5db2d6a68cf83bd4f5419071b95f979374d3184599d6c8", + strip_prefix = "urcrypt-{version}", + url = "https://github.com/urbit/urcrypt/archive/{version}.tar.gz", + version = "b970baefa6e0a680fffa2b2ee19c956a4ae20355", +) + versioned_http_archive( name = "uv", build_file = "//bazel/third_party/uv:uv.BUILD", diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel index bb93f5d26c..5ac74d0b96 100644 --- a/bazel/BUILD.bazel +++ b/bazel/BUILD.bazel @@ -11,7 +11,6 @@ refresh_compile_commands( "//pkg/ent", "//pkg/noun", "//pkg/ur", - "//pkg/urcrypt", "//pkg/vere:urbit", ], # No need to add flags already in .bazelrc. They're automatically picked up. @@ -19,4 +18,4 @@ refresh_compile_commands( # Wildcard patterns, like //... for everything, *are* allowed here, just like a build. # As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions # And if you're working on a header-only library, specify a test or binary target that compiles it. -) \ No newline at end of file +) diff --git a/bazel/third_party/urcrypt/BUILD.bazel b/bazel/third_party/urcrypt/BUILD.bazel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bazel/third_party/urcrypt/urcrypt.BUILD b/bazel/third_party/urcrypt/urcrypt.BUILD new file mode 100644 index 0000000000..973830447d --- /dev/null +++ b/bazel/third_party/urcrypt/urcrypt.BUILD @@ -0,0 +1,28 @@ +load("@rules_foreign_cc//foreign_cc:defs.bzl", "configure_make") + +filegroup( + name = "all", + srcs = glob(["**"]), +) + +configure_make( + name = "urcrypt", + autogen = True, + configure_in_place = True, + configure_options = [ + "--disable-shared", + ], + copts = [ + "-Wall", + "-g", + "-O3", + ], + deps = [ + "@aes_siv", + "@openssl", + "@secp256k1" + ], + lib_source = ":all", + out_static_libs = ["liburcrypt.a"], + visibility = ["//visibility:public"], +) diff --git a/pkg/noun/BUILD.bazel b/pkg/noun/BUILD.bazel index 964e4bf60f..a4efaeaff6 100644 --- a/pkg/noun/BUILD.bazel +++ b/pkg/noun/BUILD.bazel @@ -34,13 +34,13 @@ vere_library( "//pkg/c3", "//pkg/ent", "//pkg/ur", - "//pkg/urcrypt", "@gmp", "@murmur3", "@openssl", "@pdjson", "@sigsegv", "@softfloat", + "@urcrypt", ] + select({ "@platforms//os:macos": ["//pkg/noun/platform/darwin"], "@platforms//os:linux": ["//pkg/noun/platform/linux"], diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index 00edefec40..00a6ae78eb 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -14,7 +14,7 @@ #include "retrieve.h" #include "serial.h" #include "trace.h" -#include "urcrypt/urcrypt.h" +#include "urcrypt.h" #include "vortex.h" #include "xtract.h" diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 9b6d47fcab..0d425e3358 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -20,7 +20,7 @@ #include "platform/rsignal.h" #include "retrieve.h" #include "trace.h" -#include "urcrypt/urcrypt.h" +#include "urcrypt.h" #include "vortex.h" #include "xtract.h" diff --git a/pkg/urcrypt/.gitignore b/pkg/urcrypt/.gitignore deleted file mode 100644 index b464b3f2f1..0000000000 --- a/pkg/urcrypt/.gitignore +++ /dev/null @@ -1,56 +0,0 @@ -*.pc -config.h -config.status -libtool - -# the following was adapted from -# https://github.com/github/gitignore/blob/991e760c1c6d50fdda246e0178b9c58b06770b90/Autotools.gitignore - -# http://www.gnu.org/software/automake - -Makefile.in -build-aux/ar-lib -/mdate-sh -/py-compile -/test-driver -/ylwrap -.deps/ -.dirstamp - -# http://www.gnu.org/software/autoconf - -autom4te.cache -/autoscan.log -/autoscan-*.log -/aclocal.m4 -build-aux/compile -/config.cache -build-aux/config.guess -/config.h.in -build-aux/config.log -build-aux/config.status -build-aux/config.sub -/configure -/configure.scan -build-aux/depcomp -build-aux/install-sh -build-aux/missing -/stamp-h1 - -# https://www.gnu.org/software/libtool/ - -build-aux/ltmain.sh - -# http://www.gnu.org/software/m4/ - -build-aux/m4/libtool.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/m4/lt~obsolete.m4 - -# Generated Makefile -# (meta build system like autotools, -# can automatically generate from config.status script -# (which is called by configure script)) -Makefile diff --git a/pkg/urcrypt/BUILD.bazel b/pkg/urcrypt/BUILD.bazel deleted file mode 100644 index 22108ea72c..0000000000 --- a/pkg/urcrypt/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -# -# LIBRARIES -# - -load("//bazel:common_settings.bzl", "vere_library") - -vere_library( - name = "urcrypt", - srcs = glob( - [ - "*.c", - "*.h", - ], - exclude = ["urcrypt.h"], - ), - hdrs = ["urcrypt.h"], - copts = [ - "-Wall", - "-g", - "-O3", - ], - include_prefix = "urcrypt", - includes = ["."], - linkstatic = True, - visibility = ["//pkg:__subpackages__"], - deps = [ - "//pkg/urcrypt/ge-additions", - "@aes_siv", - "@argon2", - "@ed25519", - "@keccak_tiny", - "@openssl", - "@scrypt", - "@secp256k1", - ], -) diff --git a/pkg/urcrypt/README.md b/pkg/urcrypt/README.md deleted file mode 100644 index 7170a906b3..0000000000 --- a/pkg/urcrypt/README.md +++ /dev/null @@ -1,33 +0,0 @@ -What is urcrypt? ----------------- -urcrypt is a library of cryptography routines used by urbit jets. - -Why is urcrypt? ---------------- -Urbit's C runtime (long the only urbit runtime) has accumulated a collection of -cryptography dependencies, some with custom additions or patches. These -libraries have different conventions and have been managed by u3 in an ad-hoc -manner. Reproducing that arrangement in other runtimes is tricky and -error-prone. The (sometimes inconsistent) logic must be reproduced and suitable -cryptography primitives must be found (or worse, written) for the new -environment. - -To ease these burdens, urcrypt isolates the quirks behind a consistent calling -convention. Everything is a little-endian byte array, and each jetted operation -has a corresponding function in the library. Jets simply unpack their nouns, -call urcrypt, and pack the results. - -What is a cryptography routine? -------------------------------- -This is more of a subjective question than it might appear. Any of the following -conditions are sufficient, but not necessary, for a function to be included in -urcrypt: - - * The routine is sensitive to side-channel attacks (encryption, etc) - * Some property of the routine is cryptographically useful (SHA, RIPE, etc) - * The routine typically lives in a crypto library, for whatever reason. - -A word on OpenSSL ------------------ -It is the library user's responsibility to initialize openssl, set custom memory -functions, etc. diff --git a/pkg/urcrypt/aes_cbc.c b/pkg/urcrypt/aes_cbc.c deleted file mode 100644 index f163bccd8c..0000000000 --- a/pkg/urcrypt/aes_cbc.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "urcrypt.h" -#include "util.h" -#include -#include - -static int -urcrypt__cbc_pad(uint8_t **message_ptr, - size_t *length_ptr, - urcrypt_realloc_t realloc_ptr) -{ - size_t length = *length_ptr, - remain = length % 16; - - if ( 0 == remain ) { - // no padding needed - return 0; - } - else { - size_t padding = 16 - remain, - padded = length + padding; - - if ( padded < length ) { - // size_t overflow - return -1; - } - else { - uint8_t *out = (*realloc_ptr)(*message_ptr, padded); - if ( NULL == out ) { - return -2; - } - else { - memset(out + length, 0, padding); - *message_ptr = out; - *length_ptr = padded; - return 0; - } - } - } -} - -static int -urcrypt__cbc_help(uint8_t **message_ptr, - size_t *length_ptr, - const AES_KEY *key, - uint8_t ivec[16], - const int enc, - urcrypt_realloc_t realloc_ptr) -{ - if ( 0 != urcrypt__cbc_pad(message_ptr, length_ptr, realloc_ptr) ) { - return -1; - } - else { - uint8_t *out = *message_ptr; - size_t length = *length_ptr; - urcrypt__reverse(16, ivec); - urcrypt__reverse(length, out); - AES_cbc_encrypt(out, out, length, key, ivec, enc); - urcrypt__reverse(length, out); - return 0; - } -} - -int -urcrypt_aes_cbca_en(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[16], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(16, key); - - if ( 0 != AES_set_encrypt_key(key, 128, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_ENCRYPT, realloc_ptr); - } -} - -int -urcrypt_aes_cbca_de(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[16], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(16, key); - - if ( 0 != AES_set_decrypt_key(key, 128, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_DECRYPT, realloc_ptr); - } -} - -int -urcrypt_aes_cbcb_en(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[24], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(24, key); - - if ( 0 != AES_set_encrypt_key(key, 192, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_ENCRYPT, realloc_ptr); - } -} - -int -urcrypt_aes_cbcb_de(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[24], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(24, key); - - if ( 0 != AES_set_decrypt_key(key, 192, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_DECRYPT, realloc_ptr); - } -} - -int -urcrypt_aes_cbcc_en(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[32], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(32, key); - - if ( 0 != AES_set_encrypt_key(key, 256, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_ENCRYPT, realloc_ptr); - } -} - -int -urcrypt_aes_cbcc_de(uint8_t **message_ptr, - size_t *length_ptr, - uint8_t key[32], - uint8_t ivec[16], - urcrypt_realloc_t realloc_ptr) -{ - AES_KEY aes_key; - - urcrypt__reverse(32, key); - - if ( 0 != AES_set_decrypt_key(key, 256, &aes_key) ) { - return -1; - } - else { - return urcrypt__cbc_help(message_ptr, length_ptr, - &aes_key, ivec, AES_DECRYPT, realloc_ptr); - } -} diff --git a/pkg/urcrypt/aes_ecb.c b/pkg/urcrypt/aes_ecb.c deleted file mode 100644 index 9b39100126..0000000000 --- a/pkg/urcrypt/aes_ecb.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "urcrypt.h" -#include "util.h" -#include - -int -urcrypt_aes_ecba_en(uint8_t key[16], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(16, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_encrypt_key(key, 128, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_ENCRYPT); - urcrypt__reverse(16, out); - return 0; - } -} - -int -urcrypt_aes_ecba_de(uint8_t key[16], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(16, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_decrypt_key(key, 128, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_DECRYPT); - urcrypt__reverse(16, out); - return 0; - } -} - -int -urcrypt_aes_ecbb_en(uint8_t key[24], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(24, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_encrypt_key(key, 192, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_ENCRYPT); - urcrypt__reverse(16, out); - return 0; - } -} - -int -urcrypt_aes_ecbb_de(uint8_t key[24], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(24, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_decrypt_key(key, 192, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_DECRYPT); - urcrypt__reverse(16, out); - return 0; - } -} - -int -urcrypt_aes_ecbc_en(uint8_t key[32], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(32, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_encrypt_key(key, 256, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_ENCRYPT); - urcrypt__reverse(16, out); - return 0; - } -} - -int -urcrypt_aes_ecbc_de(uint8_t key[32], uint8_t block[16], uint8_t out[16]) -{ - AES_KEY aes_key; - - urcrypt__reverse(32, key); - urcrypt__reverse(16, block); - - if ( 0 != AES_set_decrypt_key(key, 256, &aes_key) ) { - return -1; - } - else { - AES_ecb_encrypt(block, out, &aes_key, AES_DECRYPT); - urcrypt__reverse(16, out); - return 0; - } -} diff --git a/pkg/urcrypt/aes_siv.c b/pkg/urcrypt/aes_siv.c deleted file mode 100644 index 7e06e769f2..0000000000 --- a/pkg/urcrypt/aes_siv.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "urcrypt.h" -#include "util.h" -#include "aes_siv.h" - -static AES_SIV_CTX* -urcrypt__aes_siv_init(uint8_t *key, - size_t key_length, - urcrypt_aes_siv_data *data, - size_t data_length) -{ - AES_SIV_CTX *ctx = AES_SIV_CTX_new(); - if ( NULL == ctx ) { - return NULL; - } - else { - urcrypt__reverse(key_length, key); - if ( 0 == AES_SIV_Init(ctx, key, key_length) ) { - AES_SIV_CTX_free(ctx); - return NULL; - } - else { - size_t i, len; - uint8_t *dat; - - for ( i = 0; i < data_length; ++i ) { - len = data[i].length; - dat = data[i].bytes; - urcrypt__reverse(len, dat); - if ( 0 == AES_SIV_AssociateData(ctx, dat, len) ) { - AES_SIV_CTX_free(ctx); - return NULL; - } - } - - return ctx; - } - } -} - -static int -urcrypt__aes_siv_en(uint8_t *key, - size_t key_length, - uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t iv[16], - uint8_t *out) -{ - AES_SIV_CTX *ctx = urcrypt__aes_siv_init(key, key_length, data, data_length); - - if ( NULL == ctx ) { - return -1; - } - else { - int ret; - urcrypt__reverse(message_length, message); - ret = AES_SIV_EncryptFinal(ctx, iv, out, message, message_length); - AES_SIV_CTX_free(ctx); - - if ( 0 == ret ) { - return -2; - } - else { - urcrypt__reverse(16, iv); - urcrypt__reverse(message_length, out); - return 0; - } - } -} - -static int -urcrypt__aes_siv_de(uint8_t *key, - size_t key_length, - uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t iv[16], - uint8_t *out) -{ - AES_SIV_CTX *ctx = urcrypt__aes_siv_init(key, key_length, data, data_length); - - if ( NULL == ctx ) { - return -1; - } - else { - int ret; - - urcrypt__reverse(message_length, message); - urcrypt__reverse(16, iv); - ret = AES_SIV_DecryptFinal(ctx, out, iv, message, message_length); - AES_SIV_CTX_free(ctx); - - if ( 0 == ret ) { - return -2; - } - else { - urcrypt__reverse(message_length, out); - return 0; - } - } -} - -int -urcrypt_aes_siva_en(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[32], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_en(key, 32, - message, message_length, data, data_length, iv, out); -} - -int -urcrypt_aes_siva_de(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[32], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_de(key, 32, - message, message_length, data, data_length, iv, out); -} - -int -urcrypt_aes_sivb_en(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[48], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_en(key, 48, - message, message_length, data, data_length, iv, out); -} - -int -urcrypt_aes_sivb_de(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[48], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_de(key, 48, - message, message_length, data, data_length, iv, out); -} - -int -urcrypt_aes_sivc_en(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[64], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_en(key, 64, - message, message_length, data, data_length, iv, out); -} - -int -urcrypt_aes_sivc_de(uint8_t *message, - size_t message_length, - urcrypt_aes_siv_data *data, - size_t data_length, - uint8_t key[64], - uint8_t iv[16], - uint8_t *out) -{ - return urcrypt__aes_siv_de(key, 64, - message, message_length, data, data_length, iv, out); -} diff --git a/pkg/urcrypt/argon.c b/pkg/urcrypt/argon.c deleted file mode 100644 index e1090dddec..0000000000 --- a/pkg/urcrypt/argon.c +++ /dev/null @@ -1,120 +0,0 @@ -#include "urcrypt.h" -#include "util.h" -#include -#include - -// library convention is to have sizes in size_t, but argon2 wants them -// in uint32_t, so here's a helper macro for ensuring equivalence. -#define SZ_32(s) ( sizeof(size_t) <= sizeof(uint32_t) || s <= 0xFFFFFFFF ) - -const char* -urcrypt_argon2(uint8_t type, - uint32_t version, - uint32_t threads, - uint32_t memory_cost, - uint32_t time_cost, - size_t secret_length, - uint8_t *secret, - size_t associated_length, - uint8_t *associated, - size_t password_length, - uint8_t *password, - size_t salt_length, - uint8_t *salt, - size_t out_length, - uint8_t *out, - urcrypt_argon2_alloc_t alloc_ptr, - urcrypt_argon2_free_t free_ptr) -{ - if ( !( SZ_32(secret_length) && - SZ_32(associated_length) && - SZ_32(password_length) && - SZ_32(salt_length) && - SZ_32(out_length) ) ) { - return "length > 32 bits"; - } - else { - int (*f)(argon2_context*); - int result; - - switch ( type ) { - default: - return "unknown type"; - case urcrypt_argon2_d: - f = &argon2d_ctx; - break; - case urcrypt_argon2_i: - f = &argon2i_ctx; - break; - case urcrypt_argon2_id: - f = &argon2id_ctx; - break; - case urcrypt_argon2_u: - f = &argon2u_ctx; - break; - } - - urcrypt__reverse(secret_length, secret); - urcrypt__reverse(associated_length, associated); - urcrypt__reverse(password_length, password); - urcrypt__reverse(salt_length, salt); - - argon2_context context = { - out, // output array, at least [digest length] in size - out_length, // digest length - password, // password array - password_length, // password length - salt, // salt array - salt_length, // salt length - secret, // optional secret data - secret_length, - associated, // optional associated data - associated_length, - time_cost, // performance cost configuration - memory_cost, - threads, - threads, - version, // algorithm version - alloc_ptr, // custom memory allocation function - free_ptr, // custom memory deallocation function - ARGON2_DEFAULT_FLAGS // by default only internal memory is cleared - }; - - result = (*f)(&context); - - if ( ARGON2_OK != result ) { - return argon2_error_message(result); - } - else { - urcrypt__reverse(out_length, out); - return NULL; - } - } -} - -int -urcrypt_blake2(size_t message_length, - uint8_t *message, - size_t key_length, - uint8_t key[64], - size_t out_length, - uint8_t *out) -{ - if ( key_length > 64 ) { - return -1; - } - else { - urcrypt__reverse(message_length, message); - urcrypt__reverse(key_length, key); - - if ( 0 != blake2b(out, out_length, - message, message_length, - key, key_length)) { - return -1; - } - else { - urcrypt__reverse(out_length, out); - return 0; - } - } -} diff --git a/pkg/urcrypt/argon2/argon2-specs.pdf b/pkg/urcrypt/argon2/argon2-specs.pdf deleted file mode 100644 index d916af6415c93ade373b61c9179f9928b2b1daa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459608 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