# BST-TIMEOUT: 3600 # testcrypto runs 99 algorithm tests against embedded # vectors; the RSA/EC keygen half is the slow one. # Measured value in the test-plan entry. # # 3600 IS A PREDICTION WITH A SOURCE, NOT A ROUND NUMBER -- and it is also the # most the runner will honour. brintos-selftest clamps this marker to # BST_SUITE_TIMEOUT_MAX (3600s by default), so a larger number here would be # silently reduced to this one; 3600 is therefore the ceiling, chosen knowing # it is the ceiling. # # The prediction: BRINTOS-562 measured libtomcrypt's upstream suite at 103.9s # native and 1649.1s on this runtime -- a 15.9x wasm32 slowdown on the same # host, the same arm and the same guest. bearssl's testcrypto measures 114.5s # native (x86-64, fra2), so it should land near 1820s, i.e. about half of this # bound. That is roughly 2x headroom, which is the right side to be wrong on: # a generous bound only lengthens the worst case of a genuine hang, while a # tight one manufactures a red in the suite that is this port's entire # acceptance gate. BRINTOS-562 shipped 1800 against a 1705s run -- 5% of its # own bound -- and had to raise it; this is that lesson applied up front. # # If the measured elapsed ever approaches 3600, the fix is NOT a bigger number # here (it would be clamped away). It is to raise BST_SUITE_TIMEOUT_MAX in the # runner's environment, or to split this suite. # # bearssl's acceptance gate is upstream's own two test programmes, packaged as # bearssl-tests by this layer's bbappend: # # testcrypto -- 99 algorithm tests against published vectors (run in ten # chunks rather than one `all`; see the workaround below) # testx509 -- 53 certificate chains against a path validator # # Both are offline and non-interactive: no network peer, no TTY, no device # node. That is what lets a TLS port close without a server on the other end. # # ONE CASE PER UPSTREAM TEST, NOT ONE PER PROGRAMME. Two cases keyed on the two # exit statuses would collapse 152 independent verdicts into two bits, and the # first red would hide the other hundred-and-fifty at exactly the moment they # matter most. # # HOW UPSTREAM REPORTS, AND WHY THE PARSING IS SHAPED THIS WAY. testcrypto # prints "Test : done." per test, or "Test : UNAVAILABLE" # for an implementation this build has no code for. It prints NO summary line, # and on a vector mismatch it writes the mismatch to stderr and calls # exit(EXIT_FAILURE) *mid-line* -- so a failing test is one whose line exists # without "done." on it, and every test after it is missing entirely. Missing # is therefore `not ok` and not `skip`: the verdict is unknown, which is the # outcome that hides best in a report that only counts what it was given. # # UNAVAILABLE IS `skip`, AND THE SET IS MEASURED, NOT PREDICTED. bearssl ships # several implementations of the same primitive and selects by what the compiler # and architecture provide. On x86-64 five are UNAVAILABLE (the POWER8 variants); # on wasm32 it is ELEVEN -- those five plus the six x86-specific ones: # # AES_pwr8 AES CTR/CBC-MAC pwr8 GHASH_pwr8 CCM aes_pwr8 EAX aes_pwr8 # AES_x86ni AES CTR/CBC-MAC x86ni GHASH_pclmul CCM aes_x86ni EAX aes_x86ni # ChaCha20_sse2 # # so 88 of the 99 run. Note what is NOT in that list: the m62/m64/i62 variants # (EC_p256_m62/m64, EC_c25519_m62/m64, RSA i62, ModPow/i62, Poly1305_ctmulq) all # run and pass. They need a 64x64->128 multiply, and the first draft of this file # predicted they would drop out on a 32-bit arm; the measured run says otherwise, # and the measurement wins. Configured absence is not lost coverage -- it is the # same verb the x86-64 reference uses for pwr8. The set is pinned in the # test-plan entry so a regression that silently disables a real implementation # shows up as a verb change on a named case rather than as a quieter total. . "$BST_LIB" TDIR=/usr/libexec/bearssl-tests # --------------------------------------------------------------------------- # 0. Locate the packaged programmes. They are deliberately not on PATH (see the # bbappend), so `require` cannot find them and the lookup is by path. if [ ! -d "$TDIR" ]; then bst_skip bearssl/present "$TDIR absent -- bearssl-tests not installed in this image" exit 0 fi bst_ok bearssl/present # The X.509 corpus is asserted before the run, so a missing payload is not # reported as a broken path validator. testx509 is compiled with a hardcoded # -DSRCDIRNAME="..", so it reads this file relative to its OWN directory's # parent -- which is why the programmes live in build/ and the data in # test/x509/, and why the run below cd's into build/ first. if [ -f "$TDIR/test/x509/alltests.txt" ]; then bst_ok bearssl/x509-corpus-present else bst_notok bearssl/x509-corpus-present "$TDIR/test/x509/alltests.txt missing -- testx509 will exit 1 before validating anything" fi # --------------------------------------------------------------------------- # 1. The library halves this port actually ships. The bare bearssl package is # empty on this arm (the bbappend builds with DLL=no and the distro links no # shared objects for the guest), so the archive and the headers are the # deliverable. Their absence must not be inferred from the programmes # running: both are statically linked and would run with neither installed. if [ -f /usr/lib/libbearssl.a ]; then bst_ok bearssl/staticdev else bst_notok bearssl/staticdev "/usr/lib/libbearssl.a not installed (bearssl-staticdev missing from the image?)" fi if [ -f /usr/include/bearssl.h ]; then bst_ok bearssl/headers else bst_notok bearssl/headers "/usr/include/bearssl.h not installed (bearssl-dev missing from the image?)" fi # brssl is upstream's command-line tool and the only thing this port puts on # PATH; it comes from the recipe's own lib_package split, not from this layer. if [ -x /usr/bin/brssl ]; then bst_ok bearssl/brssl-present else bst_notok bearssl/brssl-present "/usr/bin/brssl not installed (bearssl-bin missing from the image?)" fi # --------------------------------------------------------------------------- # 2. Run testcrypto IN CHUNKS, not as one `testcrypto all`. # # BRINTOS-WORKAROUND: brintos/linux-in-the-browser#159 revisit -- `testcrypto all` in a single # process runs the HOST guest process out of memory on this runtime. Measured # on the staged rootfs: one process reached 18,692 MiB and was still growing at # 2,858 MiB/min when the harness watchdog killed it, having produced no output; # the SAME 99 tests split across the ten processes below peak at 1,485 MiB and # all ten exit 0. The tests are identical and their order is preserved, so this # costs no coverage -- it only bounds what any one process is asked to hold. # Collapse this back to a single `./testcrypto all` when the issue closes; the # parser below does not care how many processes produced the text. # # Output is captured rather than echoed: the progress dots are several kilobytes # and would otherwise all cross the guest's console. stderr is folded in because # that is where a vector mismatch is written. # AND THE OUTPUT GOES TO A FILE, NOT INTO A SHELL VARIABLE. This is the second # half of the same workaround, and it was measured the same way. Running the ten # chunks with their output on the tty peaks at 1,485 MiB; running the identical # ten chunks with their output captured by command substitution -- # `_o=$(./testcrypto ...)` -- reaches 10,612 MiB at 2,507 MiB/min and is killed. # The compute is identical, so it is the capture that costs: testcrypto emits # roughly 50,000 progress characters, and moving them through a pipe into an ash # variable is what grows the host. /tmp is a real in-guest tmpfs (the rootfs is # read-only), so the run writes there and every read below is a FILE REDIRECT # rather than a pipe. TC_LOG=/tmp/bearssl-testcrypto.out TC_RC=0; TC_CHUNK_BAD="" : > "$TC_LOG" _tc_chunk() { _label=$1; shift ( cd "$TDIR/build" && ./testcrypto "$@" >> "$TC_LOG" 2>&1 ); _r=$? if [ "$_r" -ne 0 ]; then TC_RC=$_r TC_CHUNK_BAD="$TC_CHUNK_BAD $_label" fi } _tc_chunk hashes MD5 SHA1 SHA224 SHA256 SHA384 SHA512 MD5_SHA1 multihash _tc_chunk mac-kdf HMAC HKDF SHAKE HMAC_DRBG AESCTR_DRBG PRF _tc_chunk aes AES_big AES_small AES_ct AES_ct64 AES_pwr8 AES_x86ni _tc_chunk aes-cc AES_CTRCBC_big AES_CTRCBC_small AES_CTRCBC_ct AES_CTRCBC_ct64 AES_CTRCBC_x86ni AES_CTRCBC_pwr8 _tc_chunk des-ch-po DES_tab DES_ct ChaCha20_ct ChaCha20_sse2 Poly1305_ctmul Poly1305_ctmul32 Poly1305_ctmulq Poly1305_i15 _tc_chunk rsa RSA_i15 RSA_i31 RSA_i32 RSA_i62 _tc_chunk ghash-ae GHASH_ctmul GHASH_ctmul32 GHASH_ctmul64 GHASH_pclmul GHASH_pwr8 CCM EAX GCM _tc_chunk ec-p256 EC_prime_i15 EC_prime_i31 EC_p256_m15 EC_p256_m31 EC_p256_m62 EC_p256_m64 _tc_chunk c25519 EC_c25519_i15 EC_c25519_i31 EC_c25519_m15 EC_c25519_m31 EC_c25519_m62 EC_c25519_m64 _tc_chunk ecdsa-mp ECDSA_i15 ECDSA_i31 modpow_i31 modpow_i62 TC_HEAD=$(head -c 400 "$TC_LOG" 2>/dev/null) if bst_execfail "$TC_HEAD"; then bst_unrun bearssl/testcrypto/run "$TC_HEAD" else # ONE PASS OVER THE LOG, AND NO FORKS IN IT. # # The first version of this parser called a helper per roster entry, each one a # command substitution that re-read the whole log -- 99 forks and 99 re-reads for # testcrypto, 53 more for testx509. Process spawn is the scarce resource on this # runtime (brintos/linux#25, brintos/linux-in-the-browser#114 both describe # per-process cost that is never returned), and a suite that forks 152 times # while a watchdog watches it is a heavy thing to ask of the guest. `read`, # `printf` and `case` are builtins, so the loop below forks nothing per line -- # the same discipline brintos-selftest's own result loop follows, and for the # same reason. # # SEEN accumulates "|>|" records. Names cannot contain '|' or '>' # (asserted when this file is generated), so the delimiters are unambiguous. TC_SEEN="" while IFS= read -r _l; do case "$_l" in "Test "*": "*) _rest=${_l#Test } TC_SEEN="$TC_SEEN|${_rest%%: *}>${_rest#*: }|" ;; esac done < "$TC_LOG" _tc_case() { # $1 = slug, $2 = upstream test name _id="bearssl/testcrypto/$1" case "$TC_SEEN" in *"|$2>"*) _v=${TC_SEEN#*"|$2>"}; _v=${_v%%"|"*} case "$_v" in *done.*) bst_ok "$_id" ;; UNAVAILABLE*) bst_skip "$_id" "upstream reports UNAVAILABLE -- no implementation of this variant on wasm32" ;; *) bst_notok "$_id" "no 'done.' terminator; the run stopped inside this test: $(_bst_1line "$_v")" ;; esac ;; *) bst_notok "$_id" "no 'Test $2:' line -- the run did not reach this test (rc=$TC_RC)" ;; esac } TC_TOTAL=99 # The 99 tests of test/test_crypto.c, in the order it runs them. # Each line is '|' -- the slug is computed here, at # generation time, so the suite needs no `tr` fork per case. while IFS= read -r _r; do [ -n "$_r" ] && _tc_case "${_r%%|*}" "${_r#*|}" done <<'BEARSSL_TC_ROSTER' MD5|MD5 SHA-1|SHA-1 SHA-224|SHA-224 SHA-256|SHA-256 SHA-384|SHA-384 SHA-512|SHA-512 MD5+SHA-1|MD5+SHA-1 MultiHash|MultiHash HMAC|HMAC HKDF|HKDF SHAKE|SHAKE HMAC_DRBG|HMAC_DRBG AESCTR_DRBG|AESCTR_DRBG TLS_PRF|TLS PRF AES_big|AES_big AES_small|AES_small AES_ct|AES_ct AES_ct64|AES_ct64 AES_pwr8|AES_pwr8 AES_x86ni|AES_x86ni AES_CTR-CBC-MAC_big|AES CTR/CBC-MAC big AES_CTR-CBC-MAC_small|AES CTR/CBC-MAC small AES_CTR-CBC-MAC_ct|AES CTR/CBC-MAC ct AES_CTR-CBC-MAC_ct64|AES CTR/CBC-MAC ct64 AES_CTR-CBC-MAC_x86ni|AES CTR/CBC-MAC x86ni AES_CTR-CBC-MAC_pwr8|AES CTR/CBC-MAC pwr8 DES_tab|DES_tab DES_ct|DES_ct ChaCha20_ct|ChaCha20_ct ChaCha20_sse2|ChaCha20_sse2 Poly1305_ctmul|Poly1305_ctmul Poly1305_ctmul32|Poly1305_ctmul32 Poly1305_ctmulq|Poly1305_ctmulq Poly1305_i15|Poly1305_i15 RSA_i15_core|RSA i15 core RSA_i15_sign|RSA i15 sign RSA_i15_OAEP|RSA i15 OAEP RSA_i15_PSS|RSA i15 PSS RSA_i15_keygen|RSA i15 keygen RSA_i31_core|RSA i31 core RSA_i31_sign|RSA i31 sign RSA_i31_OAEP|RSA i31 OAEP RSA_i31_PSS|RSA i31 PSS RSA_i31_keygen|RSA i31 keygen RSA_i32_core|RSA i32 core RSA_i32_sign|RSA i32 sign RSA_i32_OAEP|RSA i32 OAEP RSA_i32_PSS|RSA i32 PSS RSA_i62_core|RSA i62 core RSA_i62_sign|RSA i62 sign RSA_i62_OAEP|RSA i62 OAEP RSA_i62_PSS|RSA i62 PSS RSA_i62_keygen|RSA i62 keygen GHASH_ctmul|GHASH_ctmul GHASH_ctmul32|GHASH_ctmul32 GHASH_ctmul64|GHASH_ctmul64 GHASH_pclmul|GHASH_pclmul GHASH_pwr8|GHASH_pwr8 CCM_aes_big|CCM aes_big CCM_aes_small|CCM aes_small CCM_aes_ct|CCM aes_ct CCM_aes_ct64|CCM aes_ct64 CCM_aes_x86ni|CCM aes_x86ni CCM_aes_pwr8|CCM aes_pwr8 EAX_aes_big|EAX aes_big EAX_aes_small|EAX aes_small EAX_aes_ct|EAX aes_ct EAX_aes_ct64|EAX aes_ct64 EAX_aes_x86ni|EAX aes_x86ni EAX_aes_pwr8|EAX aes_pwr8 GCM|GCM EC_prime_i15|EC_prime_i15 EC_prime_i15_keygen|EC_prime_i15 keygen EC_prime_i31|EC_prime_i31 EC_prime_i31_keygen|EC_prime_i31 keygen EC_p256_m15|EC_p256_m15 EC_p256_m15_keygen|EC_p256_m15 keygen EC_p256_m31|EC_p256_m31 EC_p256_m31_keygen|EC_p256_m31 keygen EC_p256_m62|EC_p256_m62 EC_p256_m62_keygen|EC_p256_m62 keygen EC_p256_m64|EC_p256_m64 EC_p256_m64_keygen|EC_p256_m64 keygen EC_c25519_i15|EC_c25519_i15 EC_c25519_i15_keygen|EC_c25519_i15 keygen EC_c25519_i31|EC_c25519_i31 EC_c25519_i31_keygen|EC_c25519_i31 keygen EC_c25519_m15|EC_c25519_m15 EC_c25519_m15_keygen|EC_c25519_m15 keygen EC_c25519_m31|EC_c25519_m31 EC_c25519_m31_keygen|EC_c25519_m31 keygen EC_c25519_m62|EC_c25519_m62 EC_c25519_m62_keygen|EC_c25519_m62 keygen EC_c25519_m64|EC_c25519_m64 EC_c25519_m64_keygen|EC_c25519_m64 keygen ECDSA-i15|ECDSA/i15 ECDSA-i31|ECDSA/i31 ModPow-i31|ModPow/i31 ModPow-i62|ModPow/i62 BEARSSL_TC_ROSTER # --------------------------------------------------------------------------- # 3. testcrypto's exit status and a floor on how much of it actually ran. # # The status is asserted in ADDITION to the per-test cases: it is the only # thing that says the programme agreed with its own report. if [ "$TC_RC" -eq 0 ]; then bst_ok bearssl/testcrypto/rc else bst_notok bearssl/testcrypto/rc "chunk(s)$TC_CHUNK_BAD exited non-zero (last rc=$TC_RC) -- a vector mismatch aborts that chunk at the failing test" fi # A build in which every implementation was UNAVAILABLE would satisfy every # case above as a skip and test nothing at all. Pin the floor. # # 60 IS A FLOOR, NOT A PREDICTION. The x86-64 reference runs 94 of 99 (5 pwr8 # UNAVAILABLE); wasm32 additionally loses the x86-specific and 128-bit-multiply # variants, which the measured run records exactly. The floor sits well below # that so it does not go false the day bearssl adds an implementation this arm # cannot use -- it is here to catch a degenerate build, not to restate the # measurement, which the test-plan entry carries instead. TC_DONE=$(grep -c 'done\.$' "$TC_LOG") printf '#diag: testcrypto rc=%s :: done=%s of %s tests, unavailable=%s\n' \ "$TC_RC" "$TC_DONE" "$TC_TOTAL" "$(grep -c 'UNAVAILABLE' "$TC_LOG")" if [ "$TC_DONE" -ge 60 ]; then bst_ok bearssl/testcrypto/ran-floor else bst_notok bearssl/testcrypto/ran-floor "only $TC_DONE tests completed, expected at least 60 to actually run" fi fi # end of the bst_execfail guard on testcrypto # --------------------------------------------------------------------------- # 4. testx509: 53 certificate chains through the path validator. # # It must run with build/ as the working directory -- see the header and the # bbappend: the binary carries a hardcoded -DSRCDIRNAME="..", so it resolves its # corpus one directory above wherever it is started from. TX_LOG=/tmp/bearssl-testx509.out ( cd "$TDIR/build" && ./testx509 > "$TX_LOG" 2>&1 ); TX_RC=$? # testx509's output is 55 short lines, so the capture that costs on testcrypto is # harmless here -- but it is read the same way for consistency, and so a future # corpus that grows does not reintroduce the problem. TX_OUT=$(head -c 2000 "$TX_LOG" 2>/dev/null) # THE KNOWN wasm32 FAILURE, NAMED SO ITS 53 REDS ARE NOT ANONYMOUS. # testx509 aborts in its own CONFIG PARSER before validating any chain: # `wrong configuration, line 13`, where line 13 is `e = 010001`. The corpus is # byte-identical to the host's (md5 checked on target) and the guest reads all # 18,815 bytes and 722 lines correctly, so this is not the payload and not the # virtiofs read path -- it reproduces from a tmpfs copy of the same bytes. It is # the parser's own key/value handling diverging on this arm; the same source # parses the same file on x86-64. Reduced to a 5-line config, the trigger is the # KEY NAME, not the data: `e` fails, `zz` parses. # # BRINTOS-WORKAROUND: brintos/hwjs-cc#50 remove -- when this closes, delete this # branch and let the ordinary per-chain parsing below stand on its own. TX_CONFBUG=0 case "$TX_OUT" in *"wrong configuration"*) TX_CONFBUG=1 ;; esac if bst_execfail "$TX_OUT"; then bst_unrun bearssl/testx509/run "$TX_OUT" elif [ "$TX_CONFBUG" -eq 1 ]; then # Every chain is reported red and ATTRIBUTED, never skipped: the validator is # present and the run failed, which is `not ok` by the BST verbs. A skip here # would read as "this image legitimately has no X.509 validation to test". bst_notok bearssl/testx509/config-parse "$(_bst_1line "$TX_OUT") -- brintos/hwjs-cc#50, config parser diverges on wasm32; corpus verified byte-identical on target" while IFS= read -r _r; do [ -n "$_r" ] || continue bst_notok "bearssl/testx509/${_r%%|*}" \ "not reached -- testx509 aborted in its config parser before validating any chain (brintos/hwjs-cc#50)" done <<'BEARSSL_TX_BLOCKED' base|base noTA|noTA anchorICA1|anchorICA1 anchorICA2|anchorICA2 directTrust|directTrust wrongName1|wrongName1 wrongName2|wrongName2 goodName1|goodName1 goodName2|goodName2 goodName3|goodName3 wrongName3|wrongName3 wrongName4|wrongName4 ignoreName1|ignoreName1 wildcard1|wildcard1 wildcard2|wildcard2 wildcard3|wildcard3 wildcard4|wildcard4 wildcard5|wildcard5 wildcard6|wildcard6 wildcard7|wildcard7 hashSHA256Only|hashSHA256Only hashSHA256Unsupported|hashSHA256Unsupported hashSHA1|hashSHA1 hashSHA224|hashSHA224 hashSHA384|hashSHA384 hashSHA512|hashSHA512 hashMD5|hashMD5 trailingGarbage|trailingGarbage badSignature1|badSignature1 badSignature2|badSignature2 ignoredSignature1|ignoredSignature1 ignoredSignature2|ignoredSignature2 rsa1016|rsa1016 rsa1017|rsa1017 rsa4096|rsa4096 date1|date1 date2|date2 date3|date3 date4|date4 notCA|notCA secp256r1|secp256r1 secp384r1|secp384r1 secp521r1|secp521r1 secp256r1-sha1|secp256r1-sha1 secp256r1-sha224|secp256r1-sha224 secp256r1-sha256|secp256r1-sha256 secp256r1-sha384|secp256r1-sha384 secp256r1-sha512|secp256r1-sha512 certpol-noncrit|certpol-noncrit certpol-noqual|certpol-noqual certpol-qualcps|certpol-qualcps certpol-qualother|certpol-qualother Name_extraction|Name extraction BEARSSL_TX_BLOCKED bst_notok bearssl/testx509/rc "testx509 exited $TX_RC at config parse (brintos/hwjs-cc#50)" else # Matched with `case`, not grep: several chain names carry regex # metacharacters (the certpol-* and secp*-sha* families contain '-' and '.' # freely), and a name compiled as a pattern would match the wrong line or none. # `case` globs, and the roster is asserted free of glob metacharacters when # this file is generated. # Same single-pass, fork-free shape as the testcrypto parser above. TX_SEEN="" while IFS= read -r _x; do case "$_x" in *": "*) TX_SEEN="$TX_SEEN|${_x%%: *}>${_x#*: }|" ;; esac done < "$TX_LOG" _tx_case() { # $1 = slug, $2 = chain name _id="bearssl/testx509/$1" case "$TX_SEEN" in *"|$2>"*) _v=${TX_SEEN#*"|$2>"}; _v=${_v%%"|"*} case "$_v" in OK) bst_ok "$_id" ;; *) bst_notok "$_id" "$(_bst_1line "$_v")" ;; esac ;; *) bst_notok "$_id" "no '$2:' line -- the run did not reach this chain (rc=$TX_RC)" ;; esac } TX_TOTAL=53 # The 53 chains of test/x509/alltests.txt, as '|'. while IFS= read -r _r; do [ -n "$_r" ] && _tx_case "${_r%%|*}" "${_r#*|}" done <<'BEARSSL_TX_ROSTER' base|base noTA|noTA anchorICA1|anchorICA1 anchorICA2|anchorICA2 directTrust|directTrust wrongName1|wrongName1 wrongName2|wrongName2 goodName1|goodName1 goodName2|goodName2 goodName3|goodName3 wrongName3|wrongName3 wrongName4|wrongName4 ignoreName1|ignoreName1 wildcard1|wildcard1 wildcard2|wildcard2 wildcard3|wildcard3 wildcard4|wildcard4 wildcard5|wildcard5 wildcard6|wildcard6 wildcard7|wildcard7 hashSHA256Only|hashSHA256Only hashSHA256Unsupported|hashSHA256Unsupported hashSHA1|hashSHA1 hashSHA224|hashSHA224 hashSHA384|hashSHA384 hashSHA512|hashSHA512 hashMD5|hashMD5 trailingGarbage|trailingGarbage badSignature1|badSignature1 badSignature2|badSignature2 ignoredSignature1|ignoredSignature1 ignoredSignature2|ignoredSignature2 rsa1016|rsa1016 rsa1017|rsa1017 rsa4096|rsa4096 date1|date1 date2|date2 date3|date3 date4|date4 notCA|notCA secp256r1|secp256r1 secp384r1|secp384r1 secp521r1|secp521r1 secp256r1-sha1|secp256r1-sha1 secp256r1-sha224|secp256r1-sha224 secp256r1-sha256|secp256r1-sha256 secp256r1-sha384|secp256r1-sha384 secp256r1-sha512|secp256r1-sha512 certpol-noncrit|certpol-noncrit certpol-noqual|certpol-noqual certpol-qualcps|certpol-qualcps certpol-qualother|certpol-qualother Name_extraction|Name extraction BEARSSL_TX_ROSTER printf '#diag: testx509 rc=%s :: ok=%s of %s chains\n' \ "$TX_RC" "$(grep -c ': OK$' "$TX_LOG")" "$TX_TOTAL" if [ "$TX_RC" -eq 0 ]; then bst_ok bearssl/testx509/rc else bst_notok bearssl/testx509/rc "testx509 exited $TX_RC" fi fi # end of the bst_execfail guard on testx509