u3_noun u3qe_shal(u3_atom a, u3_atom b) { c3_assert(_(u3a_is_cat(a))); c3_y* fat_y = u3a_malloc(a + 1); u3r_bytes(0, a, fat_y, b); { c3_y dig_y[64]; #if defined(U3_OS_osx) CC_SHA512_CTX ctx_h; CC_SHA512_Init(&ctx_h); CC_SHA512_Update(&ctx_h, fat_y, a); CC_SHA512_Final(dig_y, &ctx_h); #else SHA512_CTX ctx_h; SHA512_Init(&ctx_h); SHA512_Update(&ctx_h, fat_y, a); SHA512_Final(dig_y, &ctx_h); #endif u3a_free(fat_y); return u3i_bytes(64, dig_y); } }
u3_noun u3qee_shar(u3_atom pub, u3_atom sek) { c3_y pub_y[32], sek_y[32], self_y[32], exp_y[64], shr_y[32]; c3_w met_pub_w, met_sek_w; met_pub_w = u3r_met(3, pub); met_sek_w = u3r_met(3, sek); if ( (met_pub_w > 32) || (met_sek_w > 32) ) { return u3m_bail(c3__exit); } u3r_bytes(0, 32, pub_y, pub); u3r_bytes(0, 32, sek_y, sek); memset(self_y, 0, 32); memset(exp_y, 0, 64); memset(shr_y, 0, 32); ed25519_create_keypair(self_y, exp_y, sek_y); ed25519_key_exchange(shr_y, pub_y, exp_y); return u3i_bytes(32, shr_y); }
// u3_noun // u3qe_shax( // u3_atom a) // { // c3_w met_w = u3r_met(3, a); // return u3qe_shay(met_w, a); // } // XX preformance u3_noun u3qe_shax(u3_atom a) { c3_w met_w = u3r_met(3, a); c3_y* fat_y = u3a_malloc(met_w + 1); u3r_bytes(0, met_w, fat_y, a); { c3_y dig_y[32]; #if defined(U3_OS_osx) CC_SHA256_CTX ctx_h; CC_SHA256_Init(&ctx_h); CC_SHA256_Update(&ctx_h, fat_y, met_w); CC_SHA256_Final(dig_y, &ctx_h); #else SHA256_CTX ctx_h; SHA256_Init(&ctx_h); SHA256_Update(&ctx_h, fat_y, met_w); SHA256_Final(dig_y, &ctx_h); #endif u3a_free(fat_y); return u3i_bytes(32, dig_y); } }
/* _http_bods_to_octs: translate body into octet-stream noun. */ static u3_noun _http_bods_to_octs(u3_hbod* bod_u) { c3_w len_w; c3_y* buf_y; u3_noun cos; { u3_hbod* bid_u; len_w = 0; for ( bid_u = bod_u; bid_u; bid_u = bid_u->nex_u ) { len_w += bid_u->len_w; } } buf_y = c3_malloc(len_w); { c3_y* ptr_y = buf_y; while ( bod_u ) { memcpy(ptr_y, bod_u->hun_y, bod_u->len_w); ptr_y += bod_u->len_w; bod_u = bod_u->nex_u; } } cos = u3i_bytes(len_w, buf_y); free(buf_y); return u3nc(len_w, cos); }
/* _unix_string_to_path(): convert c string to u3_noun path * * c string must begin with the pier path plus mountpoint */ static u3_noun _unix_string_to_path_helper(c3_c* pax_c) { c3_assert(pax_c[-1] == '/'); c3_c* end_w = strchr(pax_c, '/'); if ( !end_w ) { end_w = strrchr(pax_c, '.'); if ( !end_w ) { return u3nc(u3i_string(pax_c), u3_nul); } else { return u3nt(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), u3i_string(end_w + 1), u3_nul); } } else { return u3nc(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), _unix_string_to_path_helper(end_w + 1)); } }
/* _unix_initial_update_file(): read file, but don't watch */ static u3_noun _unix_initial_update_file(c3_c* pax_c) { struct stat buf_u; c3_i fid_i = open(pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; if ( fid_i < 0 || fstat(fid_i, &buf_u) < 0 ) { if ( ENOENT == errno ) { return u3_nul; } else { uL(fprintf(uH, "error opening initial file %s: %s\r\n", pax_c, strerror(errno))); return u3_nul; } } len_ws = buf_u.st_size; dat_y = c3_malloc(len_ws); red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { uL(fprintf(uH, "error closing initial file %s: %s\r\n", pax_c, strerror(errno))); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { uL(fprintf(uH, "error reading initial file %s: %s\r\n", pax_c, strerror(errno))); } else { uL(fprintf(uH, "wrong # of bytes read in initial file %s: %d %d\r\n", pax_c, len_ws, red_ws)); } free(dat_y); return u3_nul; } else { u3_noun pax = _unix_string_to_path_helper(pax_c + strlen(U3_LIB) + 6); /* XX VERY BAD */ u3_noun mim = u3nt(c3__text, u3i_string("plain"), u3_nul); u3_noun dat = u3nt(mim, len_ws, u3i_bytes(len_ws, dat_y)); free(dat_y); return u3nc(u3nt(pax, u3_nul, dat), u3_nul); } }
/* _term_io_suck_char(): process a single character. */ static void _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) { u3_utat* tat_u = &uty_u->tat_u; if ( c3y == tat_u->esc.ape ) { if ( c3y == tat_u->esc.bra ) { switch ( cay_y ) { default: { _term_it_write_txt(uty_u, uty_u->ufo_u.out.bel_y); break; } case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break; case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break; case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break; case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break; } tat_u->esc.ape = tat_u->esc.bra = c3n; } else { if ( (cay_y >= 'a') && (cay_y <= 'z') ) { tat_u->esc.ape = c3n; _term_io_belt(uty_u, u3nc(c3__met, cay_y)); } else if ( ('[' == cay_y) || ('O' == cay_y) ) { tat_u->esc.bra = c3y; } else { tat_u->esc.ape = c3n; _term_it_write_txt(uty_u, uty_u->ufo_u.out.bel_y); } } } else if ( 0 != tat_u->fut.wid_w ) { tat_u->fut.syb_y[tat_u->fut.len_w++] = cay_y; if ( tat_u->fut.len_w == tat_u->fut.wid_w ) { u3_noun huv = u3i_bytes(tat_u->fut.wid_w, tat_u->fut.syb_y); u3_noun wug; // uL(fprintf(uH, "muck-utf8 len %d\n", tat_u->fut.len_w)); // uL(fprintf(uH, "muck-utf8 %x\n", huv)); wug = u3do("turf", huv); // uL(fprintf(uH, "muck-utf32 %x\n", tat_u->fut.len_w)); tat_u->fut.len_w = tat_u->fut.wid_w = 0; _term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul)); } } else { if ( (cay_y >= 32) && (cay_y < 127) ) { _term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul)); } else if ( 0 == cay_y ) { _term_it_write_txt(uty_u, uty_u->ufo_u.out.bel_y); } else if ( 8 == cay_y || 127 == cay_y ) { _term_io_belt(uty_u, u3nc(c3__bac, u3_nul)); } else if ( 13 == cay_y ) { _term_io_belt(uty_u, u3nc(c3__ret, u3_nul)); } else if ( cay_y <= 26 ) { _term_io_belt(uty_u, u3nc(c3__ctl, ('a' + (cay_y - 1)))); } else if ( 27 == cay_y ) { tat_u->esc.ape = c3y; } else if ( cay_y >= 128 ) { tat_u->fut.len_w = 1; tat_u->fut.syb_y[0] = cay_y; if ( cay_y <= 224 ) { tat_u->fut.wid_w = 2; } else if ( cay_y <= 240 ) { tat_u->fut.wid_w = 3; } else tat_u->fut.wid_w = 4; } } }
/* _unix_update_file(): update file, producing list of changes * * when scanning through files, if dry, do nothing. otherwise, mark as * dry, then check if file exists. if not, remove self from node list * and add path plus sig to %into event. otherwise, read the file and * get a mug checksum. if same as mug_w, move on. otherwise, overwrite * mug_w with new mug and add path plus data to %into event. */ static u3_noun _unix_update_file(u3_ufil* fil_u) { c3_assert( c3n == fil_u->dir ); if ( c3y == fil_u->dry ) { return u3_nul; } fil_u->dry = c3y; struct stat buf_u; c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; if ( fid_i < 0 || fstat(fid_i, &buf_u) < 0 ) { if ( ENOENT == errno ) { return u3nc(u3nc(_unix_string_to_path(fil_u->pax_c), u3_nul), u3_nul); } else { uL(fprintf(uH, "error opening file %s: %s\r\n", fil_u->pax_c, strerror(errno))); return u3_nul; } } // So, if file gets deleted and then quickly re-added, like vim and // other editors do, we lose the notification. This is a bad thing, // so we always stop and restart the notification. uv_fs_event_stop(&fil_u->was_u); c3_w ret_w = uv_fs_event_start(&fil_u->was_u, _unix_fs_event_cb, fil_u->pax_c, 0); if ( 0 != ret_w ) { uL(fprintf(uH, "update file event start: %s\n", uv_strerror(ret_w))); c3_assert(0); } len_ws = buf_u.st_size; dat_y = c3_malloc(len_ws); red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { uL(fprintf(uH, "error closing file %s: %s\r\n", fil_u->pax_c, strerror(errno))); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { uL(fprintf(uH, "error reading file %s: %s\r\n", fil_u->pax_c, strerror(errno))); } else { uL(fprintf(uH, "wrong # of bytes read in file %s: %d %d\r\n", fil_u->pax_c, len_ws, red_ws)); } free(dat_y); return u3_nul; } else { c3_w mug_w = u3r_mug_bytes(dat_y, len_ws); if ( mug_w == fil_u->mug_w ) { free(dat_y); return u3_nul; } else if ( mug_w == fil_u->gum_w ) { fil_u->mug_w = mug_w; free(dat_y); return u3_nul; } else { fil_u->mug_w = mug_w; u3_noun pax = _unix_string_to_path(fil_u->pax_c); u3_noun mim = u3nt(c3__text, u3i_string("plain"), u3_nul); u3_noun dat = u3nt(mim, len_ws, u3i_bytes(len_ws, dat_y)); free(dat_y); return u3nc(u3nt(pax, u3_nul, dat), u3_nul); } } }
u3_noun u3qe_argon2( // configuration params, u3_atom out, u3_atom type, u3_atom version, u3_atom threads, u3_atom mem_cost, u3_atom time_cost, u3_atom wik, u3_atom key, u3_atom wix, u3_atom extra, // input params u3_atom wid, u3_atom dat, u3_atom wis, u3_atom sat ) { c3_assert( _(u3a_is_cat(out)) && _(u3a_is_cat(type)) && _(u3a_is_cat(version)) && _(u3a_is_cat(threads)) && _(u3a_is_cat(mem_cost)) && _(u3a_is_cat(time_cost)) && _(u3a_is_cat(wik)) && _(u3a_is_cat(wix)) && _(u3a_is_cat(wid)) && _(u3a_is_cat(wis)) ); // flip endianness for argon2 key = u3qc_rev(3, wik, key); extra = u3qc_rev(3, wix, extra); dat = u3qc_rev(3, wid, dat); sat = u3qc_rev(3, wis, sat); // atoms to byte arrays c3_y bytes_key[wik]; u3r_bytes(0, wik, bytes_key, key); c3_y bytes_extra[wix]; u3r_bytes(0, wix, bytes_extra, extra); c3_y bytes_dat[wid]; u3r_bytes(0, wid, bytes_dat, dat); c3_y bytes_sat[wis]; u3r_bytes(0, wis, bytes_sat, sat); c3_y outhash[out]; argon2_context context = { outhash, // output array, at least [digest length] in size out, // digest length bytes_dat, // password array wid, // password length bytes_sat, // salt array wis, // salt length bytes_key, wik, // optional secret data bytes_extra, wix, // optional associated data time_cost, mem_cost, threads, threads, // performance cost configuration version, // algorithm version argon2_alloc, // custom memory allocation function argon2_free, // custom memory deallocation function ARGON2_DEFAULT_FLAGS // by default only internal memory is cleared }; int argon_res; switch ( type ) { default: fprintf(stderr, "\nunjetted argon2 variant %i\n", type); u3m_bail(c3__exit); break; // case c3__d: argon_res = argon2d_ctx(&context); break; // case c3__i: argon_res = argon2i_ctx(&context); break; // case c3__id: argon_res = argon2id_ctx(&context); break; // case c3__u: argon_res = argon2u_ctx(&context); break; } if ( ARGON2_OK != argon_res ) { fprintf(stderr, "\nargon2 error: %s\n", argon2_error_message(argon_res)); u3m_bail(c3__exit); } u3z(key); u3z(extra); u3z(dat); u3z(sat); return u3kc_rev(3, out, u3i_bytes(out, outhash)); }