GitHub - kern-werk/cosign-verify

GitHub

2 min read Original article ↗

Verify Cosign blob signatures in ~150 lines of freestanding C — no libc required, no allocation, no RNG, no dependencies beyond the vendored sources in this folder. Small enough to run inside a kernel module.

More info on our Sigstore blogpost.

Compatibility contract

The supported subset of cosign is exactly key-pair blob signatures:

cosign sign-blob --key <priv|kms-uri> --tlog-upload=false \
                 --output-signature blob.sig blob
# cosign >= 3.x additionally needs: --use-signing-config=false

# what this library verifies is bit-for-bit what this accepts:
cosign verify-blob --key pub.pem --signature blob.sig \
                   --insecure-ignore-tlog=true blob

Wire format: blob.sig is base64(DER ECDSA-Sig-Value{r,s}) — an ECDSA-P256 signature over SHA-256(blob). Cosign only generates ECDSA-P256/SHA-256 keys, so this is the only algorithm pair implemented.

API

Everything is in cosign_verify.h (header-only, static inline), on top of the vendored sources:

/* digest: SHA-256 of the blob. sig: raw .sig file contents.
 * pk: raw 64-byte P-256 point X||Y.
 * Returns 0 on a good signature, -1 on anything else. */
int cosignverify_verify_digest(const uint8_t *sig, unsigned long sig_len,
                             const uint8_t digest[32],
                             const uint8_t pk[64]);

Extract the raw 64-byte public key from cosign's PEM:

openssl pkey -pubin -in cosign.pub -outform DER | tail -c 64 > pub.raw64

Stack use is a few hundred bytes; the base64 decoder is strict (canonical encodings only) and the DER unpacking is mincrypt's dsa_sig_unpack.

Testing

Dependencies sources

what source
third_party/p256/ AOSP libmincrypt @ 669ecc2f
third_party/sha256/ AOSP libmincrypt @ same commit

The vendored files carry minimal, documented local changes (flattened include paths, unused libc includes dropped) so they compile freestanding. Everything else is byte-identical to upstream. The mincrypt P-256 code is the verifier Android used for verified boot: integer-only, constant time, no heap.