. "$BST_LIB" # libksba is GnuPG's X.509 and CMS library -- the code gpgsm and dirmngr use to # parse certificates, CRLs and PKCS#7/CMS messages, and to build PKCS#10 # requests. It links libgpg-error and carries no crypto of its own: signatures # come back as canonical S-expressions for libgcrypt to verify. # # The distro is static-only, so what the image gets is /usr/lib/libksba.a, # /usr/include/ksba.h, ksba.pc, the aclocal macro, and poky's binconfig-disabled # refusal stub in place of ksba-config. There is NO executable in this package on # this arm -- nothing here is reachable from a shell, and a payload-only suite # could assert only that an archive and a header exist, which would pass just as # happily if every entry point in the archive trapped on first call. # # --------------------------------------------------------------------------- # WHY THIS SUITE IS A PROBE AND NOT A PAYLOAD LIST # # BRINTOS-217 is the precedent: oniguruma COMPILED and PACKAGED perfectly on this # arm and then returned silently wrong offsets to every caller. libksba is placed # worse for that failure mode than most, because it is A PARSER OF # ATTACKER-SUPPLIED DER. Its failure mode is not a crash but a WRONG ANSWER: a # misread length, an off-by-one tag walk or a bad base-128 OID decode yields a # certificate whose subject, validity window or key usage is quietly not the one # on the wire, and nothing downstream can tell. # # So data/libksba-probe is cross-linked with wasmcc-glibc against THE VERY # ARCHIVE THAT SHIPS (/usr/lib/libksba.a over /usr/lib/libgpg-error.a), staged to # $TMPDIR and run here. Its source is src/libksba_probe.c, where each group is # documented. Six real DER objects from libksba's own tests/samples are COMPILED # INTO it rather than shipped as data files: the bytes cannot drift from the # expectations captured against them, and the parser is driven from memory, so # nothing depends on the rootfs being writable (it is read-only at browser # runtime). # # EVERY EXPECTED VALUE IS THE VALUE A NATIVE x86_64 BUILD OF THE IDENTICAL 1.6.6 # RELEASE PRODUCES, captured before this suite was ever run on target. Nothing # the probe prints is a pointer, a pid, a size_t width or a timestamp, so no # value is ALLOWED to differ between the two machines: a single disagreement is a # defect, not a platform difference to reason about. Blobs too large to print are # compared by length and a 32-bit FNV-1a masked to 32 bits, which is identical on # a 32-bit and a 64-bit machine. # # --------------------------------------------------------------------------- # HOW THE PROBE'S CASES REACH THIS REPORT # # The 206 probe cases are NOT re-listed here. Each `KS- OK/FAIL` line the # probe prints is turned into one `libksba/` result below, so every case # still names itself in the browser-verify report -- but the list cannot drift # out of step with the probe the way a hand-copied one does. # # What a derived list loses is the ability to notice cases that never ran, since # a probe that emitted half its output would simply report half as many greens. # That is why the COUNT is asserted (probe-case-count), alongside the probe's own # tally and its exit status. Those three are what make the derived list safe; do # not drop one while keeping the loop. # # --------------------------------------------------------------------------- # TWO THINGS THAT LOOK LIKE FAULTS AND ARE NOT # # - `ksba-config` exits non-zero. That is poky's binconfig-disabled stub doing # its job, and the refusal is asserted rather than skipped -- which is what # keeps a silently-restored, wrong-prefix config script from shipping. # - The probe writes `ksba: ber-decoder: node '?': premature EOF` to STDERR # during ksba_cms_identify(). That is libksba tracing its own bounded peek at # the outer content type; identify() still returns the right answer, and the # line reproduces identically on native x86_64. It is captured to a separate # file below rather than merged into stdout, because interleaving it into the # probe's output would split the result line it lands in. incd=/usr/include lib=/usr/lib/libksba.a pc=/usr/lib/pkgconfig/ksba.pc hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } # --- the payload ------------------------------------------------------------ # The archive and the header are the whole shipped surface, so their absence is # reported as its own case rather than as a probe that would not have linked. hasfile libksba/lib-archive "$lib" hasfile libksba/header-ksba-h "$incd/ksba.h" hasfile libksba/pkgconfig-file "$pc" hasfile libksba/aclocal-macro /usr/share/aclocal/ksba.m4 hdr=$(cat "$incd/ksba.h" 2>/dev/null) pcbody=$(cat "$pc" 2>/dev/null) # THE VERSION IS ASSERTED AS AGREEMENT, NOT AS A LITERAL. libksba derives its # version string in configure, so it depends on how the package was built rather # than on which release it is: the tarball's own shipped configure yields # "1.6.6", while a build that autoreconfs first -- which poky does -- has no git # checkout to describe and may yield "1.6.6-unknown". Both are the same release, # and pinning the literal would encode the build method and go red on a correct # package. What has to hold is that the header, the pkg-config file and the # library agree; the probe's ver-header-match case ties the running archive to # the header it compiled against, and this ties that header to the .pc. hdrver=$(printf '%s\n' "$hdr" | sed -n 's/^#define KSBA_VERSION "\(.*\)"$/\1/p') pcver=$(printf '%s\n' "$pcbody" | sed -n 's/^Version: *//p') if [ -n "$hdrver" ]; then bst_ok libksba/header-version else bst_notok libksba/header-version "no KSBA_VERSION in $incd/ksba.h"; fi if [ -n "$hdrver" ] && [ "$hdrver" = "$pcver" ]; then bst_ok libksba/header-pc-version-agree else bst_notok libksba/header-pc-version-agree "header '$hdrver' vs ksba.pc '$pcver'"; fi # The numeric macro is the release's own 0xMMNNPP rather than the configure # string, so it is asserted literally. has libksba/header-version-number '#define KSBA_VERSION_NUMBER 0x010606' "$hdr" # Unlike libassuan's assuan.h and libgpg-error's gpg-error.h, ksba.h is NOT a # wordsize dispatcher -- it is the real header and declares the API directly. # Asserting a declaration that only the real header carries is what distinguishes # a correctly packaged -dev from a stub. has libksba/header-cert-type 'typedef struct ksba_cert_s *ksba_cert_t;' "$hdr" has libksba/header-cms-type 'typedef struct ksba_cms_s *ksba_cms_t;' "$hdr" has libksba/header-sexp-type 'typedef unsigned char *ksba_sexp_t;' "$hdr" has libksba/header-isotime-type 'typedef char ksba_isotime_t[16];' "$hdr" has libksba/header-ct-signed 'KSBA_CT_SIGNED_DATA = 2' "$hdr" has libksba/header-sr-ready 'KSBA_SR_READY = 6' "$hdr" has libksba/header-keyusage 'KSBA_KEYUSAGE_KEY_CERT_SIGN = 32' "$hdr" has libksba/header-der-builder 'ksba_der_t ksba_der_builder_new (unsigned int nitems);' "$hdr" # THE ARCHIVE'S CONTENTS, WITHOUT BINUTILS. This image ships no `ar` and no `nm`, # and reaching for host binutils would not help either: every archive member is # LLVM bitcode, because -flto compile output on this arm is IR rather than an ELF # object, so `nm` answers "file format not recognized". (That same opacity is # what broke libgpg-error's own configure, which sized its public lock object by # running objdump over a compiled probe.) # # So the names are asserted as BYTES in the archive: ar's member headers and the # archive symbol index both store plain ASCII, and grep is on the image. What # that cannot show -- that a name is DEFINED rather than merely referenced -- is # exactly what the probe shows, by linking against this same archive and calling # through it. inar() { if grep -qa -- "$2" "$lib" 2>/dev/null; then bst_ok "$1"; else bst_notok "$1" "not in archive: $2"; fi; } # Members are plain-named here (cert.o, cms.o), not libtool-mangled the way # libassuan's libassuan_la-*.o are -- libksba's Makefile.am builds them directly. inar libksba/archive-cert cert.o inar libksba/archive-cms cms.o inar libksba/archive-cms-parser cms-parser.o inar libksba/archive-crl crl.o inar libksba/archive-ocsp ocsp.o inar libksba/archive-certreq certreq.o inar libksba/archive-ber-decoder ber-decoder.o inar libksba/archive-der-builder der-builder.o inar libksba/archive-keyinfo keyinfo.o inar libksba/archive-oid oid.o inar libksba/archive-dn dn.o # The symbols a consumer links. inar libksba/symbol-cert-new ksba_cert_new inar libksba/symbol-cert-parse ksba_cert_init_from_mem inar libksba/symbol-cms-parse ksba_cms_parse inar libksba/symbol-crl-parse ksba_crl_parse inar libksba/symbol-ocsp-build ksba_ocsp_build_request inar libksba/symbol-der-builder ksba_der_builder_new inar libksba/symbol-oid-to-str ksba_oid_to_str inar libksba/symbol-dn-der2str ksba_dn_der2str # ksba.pc names libgpg-error as its dependency; a port that lost that link builds # here and fails in the first consumer that trusts pkg-config. has libksba/pkgconfig-name 'Name: ksba' "$pcbody" has libksba/pkgconfig-libs '-lksba' "$pcbody" has libksba/pkgconfig-requires 'gpg-error' "$pcbody" has libksba/pkgconfig-apiver 'api_version=1' "$pcbody" # poky's binconfig-disabled replaces ksba-config with a stub that refuses and # exits non-zero. Asserting the refusal (rather than skipping it) is what keeps a # silently-restored, wrong-prefix config script from shipping. if [ -e /usr/bin/ksba-config ]; then out=$(/usr/bin/ksba-config --libs 2>&1); rc=$? if [ "$rc" -ne 0 ]; then bst_ok libksba/binconfig-disabled else bst_notok libksba/binconfig-disabled "ksba-config answered (rc=0): $out"; fi else bst_skip libksba/binconfig-disabled "no /usr/bin/ksba-config on this image" fi # --- the library RUNNING, via the cross-linked probe ------------------------- probe=${TMPDIR:-/tmp}/bst-libksba-probe.$$ perr=${TMPDIR:-/tmp}/bst-libksba-err.$$ if cp "$BST_DATA/libksba-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then # stderr goes to its own file, NOT merged: libksba traces its bounded peek in # ksba_cms_identify() to stderr, and an unbuffered stderr write landing inside # a block-buffered stdout line would split the result line it lands in. out=$("$probe" 2>"$perr"); rc=$? # One BST case per probe case, named by the probe's own case name. printf '%s\n' "$out" | while IFS= read -r ln; do case "$ln" in KS-SUMMARY*) ;; KS-*" OK") nm=${ln#KS-}; nm=${nm% OK} bst_ok "libksba/$nm" ;; KS-*" FAIL("*) nm=${ln#KS-}; nm=${nm%% FAIL(*} det=${ln#*FAIL(}; det=${det%)} bst_notok "libksba/$nm" "$(_bst_1line "$det")" ;; esac done # The three gates that make the derived list above safe. Without them a probe # that emitted half its cases would report half as many greens and no red. ncase=$(printf '%s\n' "$out" | grep -c '^KS-.* \(OK\|FAIL(\)') check_eq libksba/probe-case-count 206 "$ncase" has libksba/probe-summary "KS-SUMMARY 206/206" "$out" check_eq libksba/probe-exit0 0 "$rc" # The value-bearing lines, which are neither OK nor FAIL and so are not in the # derived list. run-version-value ties the RUNTIME version string to the header # that SHIPS -- a -dev packaged from a different build than its archive fails # exactly this case and nothing else. It is compared, not pinned, for the # reason header-version is. runver=$(printf '%s\n' "$out" | sed -n 's/^KS-ver-value //p') if [ -n "$hdrver" ]; then check_eq libksba/run-version-value "$hdrver" "$runver" else bst_notok libksba/run-version-value "no KSBA_VERSION in the shipped header to compare against" fi check_eq libksba/run-dn-der-len 86 \ "$(printf '%s\n' "$out" | sed -n 's/^KS-dn-der-len //p')" # the certificate carried INSIDE the attached CMS message, parsed as a real # cert object rather than returned as an opaque handle check_eq libksba/run-cms-embedded-cert-subject \ 'CN=Edward.Tester,OU=Testlab,O=g10 Code GmbH,C=DE' \ "$(printf '%s\n' "$out" | sed -n 's/^KS-cms-att-embedded-cert-subject-value //p')" # The stderr trace is asserted to be PRESENT and to be the only thing there: # it reproduces on native x86_64, so its disappearance would mean the identify # path stopped running, and anything else appearing would be new. if [ -s "$perr" ]; then has libksba/probe-stderr-known 'ber-decoder' "$(cat "$perr")" else bst_notok libksba/probe-stderr-known "expected libksba's ber-decoder trace on stderr, got nothing" fi rm -f "$probe" "$perr" else bst_notok libksba/run-stage "cannot stage $BST_DATA/libksba-probe" fi