# monocypher -- the compact, dependency-free modern-primitives library, ported # to the wasm32-hwjs glibc image under BRINTOS-312. # # monocypher ships NO command-line tool of any kind, so -- exactly as for # libsodium (BRINTOS-311) -- nothing in the image links it and a cross-linked # consumer is the only thing that can show the library RUNS rather than merely # installs. This suite drives TWO such consumers, and they are deliberately # different in kind: # # 1. data/monocypher-vectors is UPSTREAM'S OWN test binary (tests/test.c + # tests/vectors.h, ~16k lines of published known-answer vectors), linked # against the very /usr/lib/libmonocypher.a that ships. It is # self-scoring: it prints "All tests OK!" and exits 0 only if every vector # matched. This is the ticket's "cover it against the upstream known-answer # vectors" requirement, at upstream's own coverage rather than ours. # # IT MUST NOT BE PASSED A SEED OF 0. utils.c seeds an xorshift64* from # `u64 random_state = 12345`, and 0 is an absorbing state for it: the # generator then emits zeros forever, the "random signatures are all # invalid" case gets an all-zero signature against an all-zero public key # -- a degenerate point that legitimately verifies -- and the run fails at # tests/test.c:936. Measured natively: seed 0 fails, the default and every # non-zero seed pass. The suite runs it with NO argument, i.e. the default # 12345, which is deterministic and reproducible. # # 2. data/monocypher-probe is OURS (src/monocypher_probe.c), 25 cases whose # expected values are PUBLISHED constants transcribed independently of # upstream's corpus -- RFC 8439 (ChaCha20, Poly1305, the IETF AEAD), # RFC 7693 (BLAKE2b), FIPS 180-4 (SHA-512), RFC 4231 (HMAC-SHA-512), # RFC 7748 (X25519), RFC 8032 (Ed25519). It scores 25/25 against a native # x86_64 build of this identical release. Its value over (1) is that it is # an INDEPENDENT transcription -- a fault that upstream's own harness and # its own vectors agreed on would still be caught here -- and that it # reports per-primitive, so a red is attributable to a primitive rather # than to "the binary died". # # ONE TRAP WORTH NAMING, because it produces a wrong answer rather than an # error: monocypher's crypto_eddsa_* is its BLAKE2b EdDSA variant, NOT RFC 8032. # RFC 8032 Ed25519 is SHA-512 based and lives in crypto_ed25519_* in # monocypher-ed25519.h. The probe uses crypto_ed25519_* for the RFC 8032 # vectors; using crypto_eddsa_* there would produce a clean-looking false red. # # THE PORT'S ONE DIVERGENCE, and this suite is its regression guard: upstream's # `library` target builds a shared object this arm cannot link, so the bbappend # builds `static-library` only. If that is ever dropped, monocypher stops # building entirely and every case below goes red. . "$BST_LIB" lib=/usr/lib/libmonocypher.a inc=/usr/include/monocypher.h inc2=/usr/include/monocypher-ed25519.h pc=/usr/lib/pkgconfig/monocypher.pc tmp=${TMPDIR:-/tmp} hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } # --- 1. what the port ships -------------------------------------------------- hasfile monocypher/archive "$lib" hasfile monocypher/header "$inc" hasfile monocypher/header-ed25519 "$inc2" hasfile monocypher/pkgconfig "$pc" # There is no shared object on this arm. Anything of the sort means the # static-only divergence in the bbappend was lost. if [ -e /usr/lib/libmonocypher.so ] || [ -e /usr/lib/libmonocypher.so.4 ]; then bst_notok monocypher/static-only "a monocypher shared object is installed on a static-only arm" else bst_ok monocypher/static-only fi # --- 2. pkg-config contents -------------------------------------------------- check_out monocypher/pc-name "Name: monocypher" cat "$pc" check_out monocypher/pc-version "4.0.3" cat "$pc" check_out monocypher/pc-libs "-lmonocypher" cat "$pc" # --- 3. the archive's member table ------------------------------------------- # The image ships no `ar`, so member names are read straight out of the archive # with grep -ao, the same way the nettle and libsodium suites do it. monocypher # is a two-object library: the core and the optional SHA-512/Ed25519 half. members=$(grep -ao '[a-z0-9-]*\.o' "$lib" 2>/dev/null | sort -u) hasmember() { if printf '%s\n' "$members" | grep -q "^$2$"; then bst_ok "$1" else bst_notok "$1" "member absent from the shipped archive: $2"; fi } hasmember monocypher/member-core monocypher.o hasmember monocypher/member-ed25519 monocypher-ed25519.o # --- 4. upstream's own known-answer vector suite ----------------------------- # Self-scoring: "All tests OK!" and exit 0 only if every published vector # matched. Run with NO seed argument -- see the header on why 0 is degenerate. vec=$tmp/bst-monocypher-vectors.$$ if cp "$BST_DATA/monocypher-vectors" "$vec" 2>/dev/null && chmod +x "$vec" 2>/dev/null; then vout=$("$vec" 2>&1); vrc=$? if [ "$vrc" -eq 0 ]; then bst_ok monocypher/vectors-exit0 else bst_notok monocypher/vectors-exit0 "rc=$vrc $(_bst_1line "$vout")"; fi case "$vout" in *"All tests OK!"*) bst_ok monocypher/vectors-all-ok ;; *) bst_notok monocypher/vectors-all-ok "$(_bst_1line "$vout")" ;; esac # The default seed must be the one upstream ships; a different seed would make # the run non-reproducible without saying so. check_out monocypher/vectors-default-seed "Random seed = 12345" printf '%s\n' "$vout" # Spot-check that the individual primitive groups actually ran, so a binary # that printed a bare "All tests OK!" without executing them cannot pass. for grp in chacha20 aead_ietf poly1305 blake2b sha512 argon2 x25519 edDSA \ ed_25519 elligator; do case "$vout" in *"$grp"*) bst_ok "monocypher/vectors-ran-$grp" ;; *) bst_notok "monocypher/vectors-ran-$grp" "upstream suite did not report group $grp" ;; esac done rm -f "$vec" else bst_notok monocypher/vectors-present "data/monocypher-vectors is missing or not executable" bst_notok monocypher/vectors-exit0 "vectors payload absent" bst_notok monocypher/vectors-all-ok "vectors payload absent" bst_notok monocypher/vectors-default-seed "vectors payload absent" for grp in chacha20 aead_ietf poly1305 blake2b sha512 argon2 x25519 edDSA \ ed_25519 elligator; do bst_notok "monocypher/vectors-ran-$grp" "vectors payload absent" done fi # --- 5. our own independently-transcribed published vectors ------------------ # Each case is named here rather than harvested from the probe's output, so a # probe that prints NOTHING still produces 25 results instead of vanishing. probe=$tmp/bst-monocypher-probe.$$ cases="verify16-equal verify32-equal verify64-equal verify16-differ verify64-differ wipe chacha20-ietf-rfc8439 poly1305-rfc8439 blake2b512-rfc7693-abc blake2b-streaming-agrees blake2b-keyed-differs sha512-fips180-abc hmacsha512-rfc4231-tc2 x25519-rfc7748-vec1 x25519-base-rfc7748-alice ed25519-rfc8032-test1-pk ed25519-rfc8032-test1-sig ed25519-check-accepts ed25519-check-rejects-tampered aead-ietf-rfc8439-ct aead-ietf-rfc8439-tag aead-lock-changes-text aead-unlock-roundtrip aead-tamper-rejected elligator-map-nonzero" if cp "$BST_DATA/monocypher-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then out=$("$probe" 2>&1); prc=$? case $prc in 0) why="probe produced no result for this case" ;; *) why="probe produced no result for this case (rc=$prc)" ;; esac for c in $cases; do case "$out" in *"P312 ok $c"*) bst_ok "monocypher/probe-$c" ;; *"P312 FAIL $c :"*) bst_notok "monocypher/probe-$c" \ "$(printf '%s\n' "$out" | sed -n "s/^P312 FAIL $c : //p" | head -1)" ;; *) bst_notok "monocypher/probe-$c" "$why" ;; esac done case "$out" in *"P312-SUMMARY pass=25 fail=0"*) bst_ok monocypher/probe-summary ;; *) bst_notok monocypher/probe-summary \ "$(printf '%s\n' "$out" | sed -n 's/^P312-SUMMARY //p' | head -1)" ;; esac check_rc monocypher/probe-exit0 0 "$probe" rm -f "$probe" else bst_notok monocypher/probe-present "data/monocypher-probe is missing or not executable" for c in $cases; do bst_notok "monocypher/probe-$c" "probe payload absent" done bst_notok monocypher/probe-summary "probe payload absent" bst_notok monocypher/probe-exit0 "probe payload absent" fi