Index: crypt.t ================================================================== --- crypt.t +++ crypt.t @@ -1,10 +1,11 @@ -- vim: ft=terra local const = { keybits = 2048; - sighash = lib.md.MBEDTLS_MD_SHA256; + sighash = constant(uint32, lib.md.MBEDTLS_MD_SHA256); } +const.keybits_c = constant(uint32,const.keybits); local err = { rawcode = terra(code: int) if code < 0 then code = -code end return code and 0xFF80 end; @@ -90,11 +91,27 @@ if pub then ofs = lib.pk.mbedtls_pk_write_pubkey_der(key, buf, const.maxdersz) else ofs = lib.pk.mbedtls_pk_write_key_der(key, buf, const.maxdersz) end - if ofs < 0 then return binblob.null() end + + if ofs == lib.asn1.MBEDTLS_ERR_ASN1_BUF_TOO_SMALL then + lib.warn("BUG: bad buffer size for lib.crypt.der") + return binblob.null() + elseif ofs == lib.pk.MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE then + lib.warn("mbedtls broken! asymmetric-key crypto unsupported") + return binblob.null() + elseif ofs == lib.pk.MBEDTLS_ERR_RSA_BAD_INPUT_DATA then + lib.warn("bad RSA input to lib.crypt.der") + return binblob.null() + elseif ofs < 0 then + var num: int8[21] + var sz = lib.str.bfmt(num, "%lld", ofs) + lib.warn("unknown MBEDTLS error ", {&num[0], sz}); + return binblob.null() + end + return binblob { ptr = buf + (const.maxdersz - ofs); ct = ofs; } end @@ -102,30 +119,57 @@ m.destroy = lib.dispatch { [ctx] = function(v) return `lib.pk.mbedtls_pk_free(&v) end; [false] = function(ptr) return `ptr:free() end; } + +terra m.pk_genrsa(pk: &ctx) +-- fuck you arm for making requiring this inane pipe-through-cat +-- what is wrong with you demented bastards + var noise: uint8[2048] + m.spray(noise,2048) + var rng: lib.drbg.mbedtls_ctr_drbg_context + var entropy: lib.entropy.mbedtls_entropy_context + lib.drbg.mbedtls_ctr_drbg_init(&rng) + lib.entropy.mbedtls_entropy_init(&entropy) + lib.drbg.mbedtls_ctr_drbg_seed(&rng, lib.entropy.mbedtls_entropy_func, &entropy, &noise[0], 2048) + var rsa = lib.pk.pk2rsa(@pk) + lib.rsa.mbedtls_rsa_init(rsa) + var e = lib.rsa.mbedtls_rsa_gen_key(rsa, lib.drbg.mbedtls_ctr_drbg_random, &rng, const.keybits_c, 3) + if e < 0 then + var buf: int8[22] + lib.bail("BUG: could not buf-generate RSA keypair; mbedtls reports error ", + lib.math.decstrs(e, &buf[21])) + end + if lib.rsa.mbedtls_rsa_check_privkey(rsa) < 0 then + lib.bail("BUG: generated bad RSA keypair") + end +end terra m.genkp(): lib.pk.mbedtls_pk_context lib.dbg('generating new keypair') var pk: ctx lib.pk.mbedtls_pk_init(&pk) - lib.pk.mbedtls_pk_setup(&pk, lib.pk.mbedtls_pk_info_from_type(lib.pk.MBEDTLS_PK_RSA)) - var rsa = [&lib.rsa.mbedtls_rsa_context](pk.pk_ctx) - lib.rsa.mbedtls_rsa_gen_key(rsa, callbacks.randomize, nil, const.keybits, 65537) - + if lib.pk.mbedtls_pk_setup(&pk, lib.pk.mbedtls_pk_info_from_type(lib.pk.MBEDTLS_PK_RSA)) < 0 then + lib.bail 'pk context setup failed' + end + m.pk_genrsa(&pk) return pk end + local binblob = lib.mem.ptr(uint8) terra m.loadpriv(buf: binblob): lib.stat(ctx) lib.dbg('parsing saved private key') var pk: ctx lib.pk.mbedtls_pk_init(&pk) - var rt = lib.pk.mbedtls_pk_parse_key(&pk, buf.ptr, buf.ct, nil, 0) + var rt = lib.pk.mbedtls_pk_parse_key(&pk, + [&uint8](buf.ptr), [intptr](buf.ct), + nil, 0, + callbacks.randomize, nil) if rt == 0 then return [lib.stat(ctx)] { ok = true, val = pk } else lib.pk.mbedtls_pk_free(&pk) return [lib.stat(ctx)] { ok = false, error = rt } @@ -156,16 +200,20 @@ if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(const.sighash), [&uint8](txt), len, hash) ~= 0 then lib.bail('could not hash message') end lib.dbg('(2/2) signing hash') - var ret = lib.pk.mbedtls_pk_sign(pk, const.sighash, hash, 0, [&uint8](sig.ptr), &osz, callbacks.randomize, nil) + var ret = lib.pk.mbedtls_pk_sign(pk, const.sighash, + hash, sizeof([hash.type]), + [&uint8](sig.ptr), 2048, &osz, + callbacks.randomize, nil) if ret ~= 0 then lib.bail('could not sign message hash') else sig:resize(osz) end return sig end + terra m.verify(pk: &ctx, txt: rawstring, len: intptr, sig: &uint8, siglen: intptr): {bool, uint8} lib.dbg('verifying signature') var osz: intptr = 0 @@ -203,11 +251,10 @@ end end lib.dbg('all hash algorithms failed') return false, 0 end - terra m.hmac(alg: hashalg, key: lib.mem.ptr(uint8), txt: lib.mem.ptr(int8), buf: &uint8) lib.md.mbedtls_md_hmac( lib.md.mbedtls_md_info_from_type(alg.id), key.ptr, key.ct, [&uint8](txt.ptr), txt.ct, @@ -258,5 +305,6 @@ end a:ipush(m.random(uint32,0,99999)) end return m + Index: default.nix ================================================================== --- default.nix +++ default.nix @@ -3,16 +3,18 @@ fetchFromGitHub ? pkg.fetchFromGitHub, terra ? pkg.terra, pkgconfig ? pkg.pkgconfig, json_c ? pkg.json_c, postgresql ? pkg.postgresql.lib, - mbedtls ? pkg.mbedtls, + mbedtlsLegacy ? pkg.mbedtls, glibc ? pkg.glibc, cmark ? pkg.cmark, inkscape ? pkg.inkscape, mongoose ? null, - lib ? pkg.lib + lib ? pkg.lib, + pypkgs ? pkg.python310Packages, + debug ? true }: let mgsrc = if mongoose != null then mongoose else fetchFromGitHub { owner = "cesanta"; repo = "mongoose"; @@ -19,17 +21,29 @@ rev = "369f44adfa38e0d8fa9667e9d6bafd7e0e3c6231"; sha256 = "17rkd7ydic39cw9sfh11mcil02vmi6jjyj2ncbxan6psak09xbrc"; }; pkv = val: p: "parsav_pkg_${p}_${val}"; pkp = pkv "prefix"; + mbedtls = mbedtlsLegacy.overrideAttrs(o: rec{ + version = "3.0-dev"; + nativeBuildInputs = o.nativeBuildInputs ++ [pypkgs.jinja2]; + src = fetchFromGitHub { + owner = "ARMmbed"; repo = "mbedtls"; + rev = "49e9fbd6bc7c970c221be6e35f6872762ddde0bc"; + sha256 = "1ips4mx8rr0kcqn7vdapx2m9xh4cayb7isbwvr98qp2ybi4pi4ai"; + }; + }); in stdenv.mkDerivation { name = "parsav"; version = "dev"; nativeBuildInputs = [terra json_c pkgconfig mbedtls]; buildInputs = [cmark inkscape postgresql postgresql.lib]; src = ./.; + dontStrip = debug; + dbg = if debug then 1 else null; + ${pkp "json-c"} = "${json_c}"; ${pkp "mbedtls"} = "${mbedtls}"; ${pkp "libc"} = "${glibc.out}"; ${pkp "cmark"} = "${cmark}"; ${pkp "inkscape"} = "${inkscape}"; Index: math.t ================================================================== --- math.t +++ math.t @@ -162,16 +162,45 @@ terra m.decstr(val: intptr, buf: &int8): rawstring -- works backwards to avoid copies. log10(2^64) ≈ 19.2 and we -- need a byte for NUL so buf MUST point to THE END OF a buffer -- at least 21 bytes long @buf = 0 - if val > 0 then while val > 0 do + if val ~= 0 then + while val > 0 do + buf = buf - 1 + var dgt = val % 10 + val = val / 10 + @buf = 0x30 + dgt + end + else buf = buf - 1 - var dgt = val % 10 - val = val / 10 - @buf = 0x30 + dgt - end else + @buf = 0x30 + end + return buf +end + +terra m.decstrs(inval: ptrdiff, buf: &int8): rawstring +-- works backwards to avoid copies. log10(2^64) ≈ 19.2 and we +-- need a byte for NUL so buf MUST point to THE END OF a buffer +-- at least 22 bytes long + @buf = 0 + var val = inval + if val ~= 0 then + if val < 0 then + val = -val + end + while val > 0 do + buf = buf - 1 + var dgt = val % 10 + val = val / 10 + @buf = 0x30 + dgt + end + if inval < 0 then + buf = buf - 1 + @buf = @"-" + end + else buf = buf - 1 @buf = 0x30 end return buf end Index: mgtool.t ================================================================== --- mgtool.t +++ mgtool.t @@ -302,11 +302,11 @@ do var newkp = lib.crypt.genkp() -- generate server privkey var kbuf: uint8[lib.crypt.const.maxdersz] var derkey = lib.crypt.der(false,&newkp, &kbuf[0]) if not derkey then - lib.bail('could not write out DER form of server pubkey!') + lib.bail('could not write out DER form of server privkey!') end dlg:server_setup_self(dbmode.arglist(1), derkey) end dlg:conf_set('instance-name', dbmode.arglist(1)) Index: parsav.t ================================================================== --- parsav.t +++ parsav.t @@ -431,12 +431,22 @@ return set end lib.err = lib.loadlib('mbedtls','mbedtls/error.h') lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h') -lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h') +lib.asn1 = lib.loadlib('mbedtls','mbedtls/asn1.h') +-- lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h') +--sigh +lib.pk = terralib.includecstring [[ + #include + mbedtls_rsa_context* pk2rsa(const mbedtls_pk_context pk) { + return mbedtls_pk_rsa(pk); + } +]] lib.md = lib.loadlib('mbedtls','mbedtls/md.h') +lib.drbg = lib.loadlib('mbedtls','mbedtls/ctr_drbg.h') +lib.entropy = lib.loadlib('mbedtls','mbedtls/entropy.h') lib.b64 = lib.loadlib('mbedtls','mbedtls/base64.h') lib.net = lib.loadlib('mongoose','mongoose.h') lib.pq = lib.loadlib('libpq','libpq-fe.h') lib.jc = lib.loadlib('mjson','mjson.h')