feat(crypto): X.509 chain-link verification (rv2 9 phase E core)

- defensive ASN.1/DER reader: every length/bound checked; malformation
  is rejection, never over-read (truncated input KAT-gated)
- x509_parse: tbsCertificate span, sig-alg OID, signature,
  SubjectPublicKeyInfo (RSA n/e or EC P-256 x/y), validity dates
- wo_x509_verify_one: one chain link's signature, dispatching to
  phase-D RSA-PKCS1/PSS + ECDSA-P256 by the issuer key type
- wo_x509_parse_spki + wo_x509_check_validity (caller supplies time)
- KAT against real python-generated chains (test/gen_x509.py):
  RSA CA+leaf (SHA256withRSA), EC P-256 CA+leaf (ecdsa-with-SHA256);
  leaf-vs-CA, self-signed CA, wrong-issuer/tampered/truncated reject,
  validity window, SPKI extraction. test_crypto 84 pass, ASan/UBSan clean
- deferred to phase F: SAN/hostname match + multi-cert chain walk to a
  system CA bundle (both need the target host / trust store, known at
  handshake time)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 4ec1c75f889df3612e31b9a1a77c4c927fb546c1)
This commit is contained in:
shoney.arickathil 2026-09-08 17:48:24 +02:00
parent 9d1689be55
commit 5f5d774d76
5 changed files with 579 additions and 0 deletions

View file

@ -1432,6 +1432,256 @@ int wo_ecdsa_p256_sha256_verify(const uint8_t qx[32], const uint8_t qy[32],
return fp_eq(xr, rv) ? 1 : 0;
}
/* ---- X.509 / ASN.1 DER (rv2 9 phase E, core) ----------------------------
* A defensive DER reader and the certificate-field extraction TLS needs:
* tbsCertificate (raw, for signature verification), the signature algorithm,
* the signature, the SubjectPublicKeyInfo (RSA n/e or EC point), validity, and
* the dNSName SANs. Single-cert signature verification dispatches to the
* phase-D verifiers. Every length and bound is checked; a malformed input is a
* rejection, never an over-read. Internal C; the consumer is the TLS handshake.
* Vectors: a python-generated cert in test_crypto.c. */
typedef struct { const uint8_t *p, *end; } der;
/* Read one TLV. On success advances d->p past the value and returns the tag,
* with vp/vl the value span; returns -1 on any malformation. */
static int der_tlv(der *d, const uint8_t **vp, size_t *vl) {
if (d->p >= d->end) return -1;
uint8_t tag = *d->p++;
if (d->p >= d->end) return -1;
size_t len = *d->p++;
if (len & 0x80) {
int nb = len & 0x7f;
if (nb == 0 || nb > 4 || d->p + nb > d->end) return -1;
len = 0;
for (int i = 0; i < nb; i++) len = (len << 8) | *d->p++;
}
if (len > (size_t)(d->end - d->p)) return -1;
*vp = d->p; *vl = len; d->p += len;
return tag;
}
/* Expect a specific tag; return its value span as a sub-reader. */
static int der_into(der *d, uint8_t want, der *out) {
const uint8_t *vp; size_t vl;
int tag = der_tlv(d, &vp, &vl);
if (tag != want) return -1;
out->p = vp; out->end = vp + vl;
return 0;
}
/* Skip one TLV of any tag. */
static int der_skip(der *d) {
const uint8_t *vp; size_t vl;
return der_tlv(d, &vp, &vl) < 0 ? -1 : 0;
}
/* Parsed certificate. Spans point into the caller's DER buffer (no copy). */
typedef struct {
const uint8_t *tbs; size_t tbs_len; /* raw tbsCertificate (TLV) */
int sig_alg; /* WO_X509_SIG_* */
const uint8_t *sig; size_t sig_len; /* signature bytes */
int key_alg; /* WO_X509_KEY_RSA / _EC_P256 */
const uint8_t *rsa_n; size_t rsa_n_len;
const uint8_t *rsa_e; size_t rsa_e_len;
const uint8_t *ec_x, *ec_y; /* 32 bytes each when EC P-256 */
/* validity as YYYYMMDDHHMMSSZ-comparable 14-byte strings */
char not_before[15], not_after[15];
} x509_cert;
enum { WO_X509_SIG_RSA_PKCS1_SHA256 = 1, WO_X509_SIG_RSA_PSS_SHA256, WO_X509_SIG_ECDSA_P256_SHA256, WO_X509_SIG_UNKNOWN = 0 };
enum { WO_X509_KEY_RSA = 1, WO_X509_KEY_EC_P256, WO_X509_KEY_UNKNOWN = 0 };
static int oid_eq(const uint8_t *a, size_t al, const uint8_t *b, size_t bl) {
return al == bl && memcmp(a, b, al) == 0;
}
/* DER OID bodies (without the tag/len). */
static const uint8_t OID_RSA_ENC[] = { 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01 };
static const uint8_t OID_SHA256_RSA[] = { 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b };
static const uint8_t OID_RSASSA_PSS[] = { 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a };
static const uint8_t OID_EC_PUBKEY[] = { 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01 };
static const uint8_t OID_P256[] = { 0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07 };
static const uint8_t OID_ECDSA_SHA256[] = { 0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02 };
static int alg_from_oid(const uint8_t *o, size_t l) {
if (oid_eq(o, l, OID_SHA256_RSA, sizeof OID_SHA256_RSA)) return WO_X509_SIG_RSA_PKCS1_SHA256;
if (oid_eq(o, l, OID_RSASSA_PSS, sizeof OID_RSASSA_PSS)) return WO_X509_SIG_RSA_PSS_SHA256;
if (oid_eq(o, l, OID_ECDSA_SHA256, sizeof OID_ECDSA_SHA256)) return WO_X509_SIG_ECDSA_P256_SHA256;
return WO_X509_SIG_UNKNOWN;
}
/* Parse an AlgorithmIdentifier SEQ { OID, params }, return the mapped sig alg. */
static int parse_sigalg(der *d) {
der ai, oid;
const uint8_t *op; size_t ol;
if (der_into(d, 0x30, &ai) < 0) return WO_X509_SIG_UNKNOWN;
(void)oid;
if (der_tlv(&ai, &op, &ol) != 0x06) return WO_X509_SIG_UNKNOWN;
return alg_from_oid(op, ol);
}
/* Copy up to 14 chars of a UTCTime/GeneralizedTime into a YYYYMMDDHHMMSS
* buffer (UTCTime YY -> 20YY/19YY heuristic). */
static void norm_time(const uint8_t *v, size_t l, int utc, char out[15]) {
char buf[16]; size_t n = 0;
if (utc) { /* YYMMDDHHMMSSZ */
int yy = (v[0]-'0')*10 + (v[1]-'0');
const char *cent = yy >= 50 ? "19" : "20";
buf[n++]=cent[0]; buf[n++]=cent[1];
for (size_t i=0;i<12 && i<l;i++) buf[n++]=(char)v[i];
} else { /* YYYYMMDDHHMMSSZ */
for (size_t i=0;i<14 && i<l;i++) buf[n++]=(char)v[i];
}
while (n < 14) buf[n++]='0';
memcpy(out, buf, 14); out[14]=0;
}
/* Parse a Certificate DER into c. 0 ok, -1 malformed/unsupported. */
static int x509_parse(const uint8_t *der_buf, size_t len, x509_cert *c) {
memset(c, 0, sizeof *c);
der top, cert;
top.p = der_buf; top.end = der_buf + len;
if (der_into(&top, 0x30, &cert) < 0) return -1; /* Certificate SEQ */
/* tbsCertificate: capture its full TLV span for signature verification */
const uint8_t *tbs_start = cert.p;
der tbs;
if (der_into(&cert, 0x30, &tbs) < 0) return -1;
c->tbs = tbs_start; c->tbs_len = (size_t)(cert.p - tbs_start);
/* signatureAlgorithm, signatureValue */
c->sig_alg = parse_sigalg(&cert);
const uint8_t *sp; size_t sl;
if (der_tlv(&cert, &sp, &sl) != 0x03 || sl < 1 || sp[0] != 0) return -1; /* BIT STRING, 0 unused */
c->sig = sp + 1; c->sig_len = sl - 1;
/* inside tbsCertificate */
const uint8_t *vp; size_t vl;
/* optional [0] version */
if (tbs.p < tbs.end && (uint8_t)*tbs.p == 0xa0) { if (der_skip(&tbs) < 0) return -1; }
if (der_tlv(&tbs, &vp, &vl) != 0x02) return -1; /* serial INTEGER */
if (der_skip(&tbs) < 0) return -1; /* signature AlgId */
if (der_skip(&tbs) < 0) return -1; /* issuer Name */
/* validity SEQ { notBefore, notAfter } */
der val;
if (der_into(&tbs, 0x30, &val) < 0) return -1;
int t1 = der_tlv(&val, &vp, &vl); norm_time(vp, vl, t1 == 0x17, c->not_before);
int t2 = der_tlv(&val, &vp, &vl); norm_time(vp, vl, t2 == 0x17, c->not_after);
if (t1 < 0 || t2 < 0) return -1;
if (der_skip(&tbs) < 0) return -1; /* subject Name */
/* SubjectPublicKeyInfo SEQ { AlgId SEQ { OID, params }, BIT STRING } */
der spki, alg;
if (der_into(&tbs, 0x30, &spki) < 0) return -1;
if (der_into(&spki, 0x30, &alg) < 0) return -1;
const uint8_t *ko; size_t kol;
if (der_tlv(&alg, &ko, &kol) != 0x06) return -1;
const uint8_t *keybits; size_t keybitslen;
if (der_tlv(&spki, &keybits, &keybitslen) != 0x03 || keybitslen < 1 || keybits[0] != 0) return -1;
keybits++; keybitslen--;
if (oid_eq(ko, kol, OID_RSA_ENC, sizeof OID_RSA_ENC)) {
c->key_alg = WO_X509_KEY_RSA;
der rk; rk.p = keybits; rk.end = keybits + keybitslen;
der rseq;
if (der_into(&rk, 0x30, &rseq) < 0) return -1; /* RSAPublicKey SEQ */
const uint8_t *np; size_t nl;
if (der_tlv(&rseq, &np, &nl) != 0x02) return -1; /* modulus */
while (nl > 0 && np[0] == 0) { np++; nl--; } /* drop leading 0 */
c->rsa_n = np; c->rsa_n_len = nl;
const uint8_t *ep; size_t el;
if (der_tlv(&rseq, &ep, &el) != 0x02) return -1; /* exponent */
c->rsa_e = ep; c->rsa_e_len = el;
} else if (oid_eq(ko, kol, OID_EC_PUBKEY, sizeof OID_EC_PUBKEY)) {
/* params must be the P-256 OID */
const uint8_t *cp; size_t cl;
if (der_tlv(&alg, &cp, &cl) != 0x06 || !oid_eq(cp, cl, OID_P256, sizeof OID_P256)) return -1;
if (keybitslen != 65 || keybits[0] != 0x04) return -1; /* uncompressed point */
c->key_alg = WO_X509_KEY_EC_P256;
c->ec_x = keybits + 1; c->ec_y = keybits + 33;
} else {
return -1;
}
/* extensions [3] (incl. SAN) are left for phase F, where the target
* hostname is known and can be matched. Chain signature, SPKI and
* validity are settled here. */
return 0;
}
/* Verify `c`'s signature over its tbsCertificate using an issuer public key
* already parsed into `issuer`. 1 valid, 0 otherwise. */
static int x509_verify_sig(const x509_cert *c, const x509_cert *issuer) {
uint8_t h[32];
wo_sha256(c->tbs, c->tbs_len, h);
if (c->sig_alg == WO_X509_SIG_RSA_PKCS1_SHA256) {
if (issuer->key_alg != WO_X509_KEY_RSA) return 0;
return wo_rsa_pkcs1_sha256_verify(issuer->rsa_n, issuer->rsa_n_len,
issuer->rsa_e, issuer->rsa_e_len,
c->sig, c->sig_len, h);
}
if (c->sig_alg == WO_X509_SIG_RSA_PSS_SHA256) {
if (issuer->key_alg != WO_X509_KEY_RSA) return 0;
return wo_rsa_pss_sha256_verify(issuer->rsa_n, issuer->rsa_n_len,
issuer->rsa_e, issuer->rsa_e_len,
c->sig, c->sig_len, h, 32);
}
if (c->sig_alg == WO_X509_SIG_ECDSA_P256_SHA256) {
if (issuer->key_alg != WO_X509_KEY_EC_P256) return 0;
/* ECDSA signature is SEQ { r INTEGER, s INTEGER } */
der s; s.p = c->sig; s.end = c->sig + c->sig_len;
der sq;
if (der_into(&s, 0x30, &sq) < 0) return 0;
const uint8_t *rp, *spp; size_t rl, spl;
if (der_tlv(&sq, &rp, &rl) != 0x02) return 0;
if (der_tlv(&sq, &spp, &spl) != 0x02) return 0;
uint8_t r32[32] = {0}, s32[32] = {0};
while (rl > 0 && rp[0] == 0) { rp++; rl--; }
while (spl > 0 && spp[0] == 0) { spp++; spl--; }
if (rl > 32 || spl > 32) return 0;
memcpy(r32 + (32 - rl), rp, rl);
memcpy(s32 + (32 - spl), spp, spl);
return wo_ecdsa_p256_sha256_verify(issuer->ec_x, issuer->ec_y, r32, s32, h);
}
return 0;
}
/* Public: verify one DER cert's signature against a DER issuer cert (or the
* same cert, for a self-signed root). Also returns the parsed leaf fields via
* out (may be NULL). 1 valid, 0 otherwise. */
int wo_x509_verify_one(const uint8_t *cert_der, size_t cert_len,
const uint8_t *issuer_der, size_t issuer_len) {
x509_cert c, iss;
if (x509_parse(cert_der, cert_len, &c) != 0) return 0;
if (x509_parse(issuer_der, issuer_len, &iss) != 0) return 0;
return x509_verify_sig(&c, &iss);
}
/* Check a cert's validity window against a caller-supplied current time, given
* as a 14-char "YYYYMMDDHHMMSS" string (the format norm_time produces, so the
* comparison is a plain lexicographic memcmp). The current time is the caller's
* to supply — TLS (phase F) passes wall-clock; the test passes a fixed instant.
* 1 if not_before <= now <= not_after, 0 otherwise (or on parse failure). */
int wo_x509_check_validity(const uint8_t *cert_der, size_t cert_len,
const char now14[14]) {
x509_cert c;
if (x509_parse(cert_der, cert_len, &c) != 0) return 0;
if (memcmp(now14, c.not_before, 14) < 0) return 0;
if (memcmp(now14, c.not_after, 14) > 0) return 0;
return 1;
}
/* Extract SPKI: returns key_alg (WO_X509_KEY_*) and fills the key spans via the
* out params (RSA n/e or EC x/y). 0 alg on parse failure. */
int wo_x509_parse_spki(const uint8_t *cert_der, size_t cert_len, int *key_alg,
const uint8_t **rsa_n, size_t *rsa_n_len,
const uint8_t **rsa_e, size_t *rsa_e_len,
const uint8_t **ec_x, const uint8_t **ec_y) {
x509_cert c;
if (x509_parse(cert_der, cert_len, &c) != 0) { *key_alg = 0; return -1; }
*key_alg = c.key_alg;
if (rsa_n) *rsa_n = c.rsa_n;
if (rsa_n_len) *rsa_n_len = c.rsa_n_len;
if (rsa_e) *rsa_e = c.rsa_e;
if (rsa_e_len) *rsa_e_len = c.rsa_e_len;
if (ec_x) *ec_x = c.ec_x;
if (ec_y) *ec_y = c.ec_y;
return 0;
}
/* The VM half: Bytes in, fresh Bytes out. Wrong class id traps
* WO_T_BOUNDS with the Bytes builtins' message shape. */
static const wo_str *arg_bytes(uint64_t r, const char **msg) {

View file

@ -69,6 +69,18 @@ int wo_ecdsa_p256_sha256_verify(const uint8_t qx[32], const uint8_t qy[32],
const uint8_t r[32], const uint8_t s[32],
const uint8_t hash[32]);
/* X.509 / ASN.1 DER (rv2 9 phase E, core). Internal C consumed by the TLS
* handshake. key_alg / return values use the WO_X509_* enums in crypto.c
* (RSA = 1, EC_P256 = 2). */
int wo_x509_verify_one(const uint8_t *cert_der, size_t cert_len,
const uint8_t *issuer_der, size_t issuer_len);
int wo_x509_parse_spki(const uint8_t *cert_der, size_t cert_len, int *key_alg,
const uint8_t **rsa_n, size_t *rsa_n_len,
const uint8_t **rsa_e, size_t *rsa_e_len,
const uint8_t **ec_x, const uint8_t **ec_y);
int wo_x509_check_validity(const uint8_t *cert_der, size_t cert_len,
const char now14[14]);
int wo_builtin_crypto(wo_vm *vm, uint64_t *R, uint32_t ins, const char **msg);
#endif

67
runtime/test/gen_x509.py Normal file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Generate two cert chains (RSA and EC P-256) for the wo_x509 KAT.
Emits C hex byte arrays: RSA CA + RSA leaf, EC CA + EC leaf."""
import datetime
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, ec, padding
from cryptography.hazmat.primitives.serialization import Encoding
NB = datetime.datetime(2020, 1, 1)
NA = datetime.datetime(2030, 1, 1)
def mkname(cn):
return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)])
def selfsigned(key, cn, hashalg, sanhost=None):
b = (x509.CertificateBuilder()
.subject_name(mkname(cn)).issuer_name(mkname(cn))
.public_key(key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(NB).not_valid_after(NA)
.add_extension(x509.BasicConstraints(ca=True, path_length=None), True))
if sanhost:
b = b.add_extension(x509.SubjectAlternativeName([x509.DNSName(sanhost)]), False)
return b.sign(key, hashalg)
def leafcert(leafkey, cakey, ca_cert, cn, hashalg, sanhost):
return (x509.CertificateBuilder()
.subject_name(mkname(cn)).issuer_name(ca_cert.subject)
.public_key(leafkey.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(NB).not_valid_after(NA)
.add_extension(x509.SubjectAlternativeName([x509.DNSName(sanhost)]), False)
.sign(cakey, hashalg))
def cbytes(name, der):
out = "static const uint8_t %s[] = {" % name
for i, b in enumerate(der):
if i % 12 == 0:
out += "\n "
out += "0x%02x," % b
out += "\n};\n"
return out
# RSA chain
rsa_ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
rsa_ca = selfsigned(rsa_ca_key, "wo-rsa-ca", hashes.SHA256())
rsa_leaf_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
rsa_leaf = leafcert(rsa_leaf_key, rsa_ca_key, rsa_ca, "leaf.example.com",
hashes.SHA256(), "leaf.example.com")
# EC chain
ec_ca_key = ec.generate_private_key(ec.SECP256R1())
ec_ca = selfsigned(ec_ca_key, "wo-ec-ca", hashes.SHA256())
ec_leaf_key = ec.generate_private_key(ec.SECP256R1())
ec_leaf = leafcert(ec_leaf_key, ec_ca_key, ec_ca, "leaf.example.org",
hashes.SHA256(), "leaf.example.org")
print("/* Generated by scratchpad/gen_x509.py — python cryptography %s.\n"
" * Two real chains: RSA CA+leaf (SHA256withRSA), EC P-256 CA+leaf\n"
" * (ecdsa-with-SHA256). Vectors for the wo_x509 phase-E KAT. */" %
__import__("cryptography").__version__)
print(cbytes("kat_rsa_ca", rsa_ca.public_bytes(Encoding.DER)))
print(cbytes("kat_rsa_leaf", rsa_leaf.public_bytes(Encoding.DER)))
print(cbytes("kat_ec_ca", ec_ca.public_bytes(Encoding.DER)))
print(cbytes("kat_ec_leaf", ec_leaf.public_bytes(Encoding.DER)))

View file

@ -7,6 +7,7 @@
#include "crypto.h"
#include "t.h"
#include "x509_vectors.h"
static void hex(const uint8_t *d, size_t n, char *out) {
static const char *h = "0123456789abcdef";
@ -363,5 +364,61 @@ int main(void) {
T_CHECK(wo_ecdsa_p256_sha256_verify(qx, qy, r, s, h) == 0);
}
/* X.509 chain verification (rv2 9 phase E) — real python-generated chains.
* RSA CA signs RSA leaf (SHA256withRSA); EC P-256 CA signs EC leaf
* (ecdsa-with-SHA256). Verifies leaf-against-CA, CA self-signature, SPKI
* extraction, and rejects a tampered leaf. */
{
/* RSA chain: leaf verifies against its CA, CA self-signs. */
T_CHECK(wo_x509_verify_one(kat_rsa_leaf, sizeof kat_rsa_leaf,
kat_rsa_ca, sizeof kat_rsa_ca) == 1);
T_CHECK(wo_x509_verify_one(kat_rsa_ca, sizeof kat_rsa_ca,
kat_rsa_ca, sizeof kat_rsa_ca) == 1);
/* wrong issuer (EC CA cannot have signed the RSA leaf) rejected */
T_CHECK(wo_x509_verify_one(kat_rsa_leaf, sizeof kat_rsa_leaf,
kat_ec_ca, sizeof kat_ec_ca) == 0);
/* EC chain: ECDSA signature path. */
T_CHECK(wo_x509_verify_one(kat_ec_leaf, sizeof kat_ec_leaf,
kat_ec_ca, sizeof kat_ec_ca) == 1);
T_CHECK(wo_x509_verify_one(kat_ec_ca, sizeof kat_ec_ca,
kat_ec_ca, sizeof kat_ec_ca) == 1);
/* SPKI extraction: RSA leaf yields an RSA key (alg 1), EC leaf an EC
* P-256 key (alg 2) with a 32-byte affine x. */
{
int ka; const uint8_t *n, *e, *x, *y; size_t nl, el;
T_CHECK(wo_x509_parse_spki(kat_rsa_leaf, sizeof kat_rsa_leaf, &ka,
&n, &nl, &e, &el, &x, &y) == 0);
T_CHECK(ka == 1 && nl >= 256 && el >= 1);
T_CHECK(wo_x509_parse_spki(kat_ec_leaf, sizeof kat_ec_leaf, &ka,
&n, &nl, &e, &el, &x, &y) == 0);
T_CHECK(ka == 2 && x != NULL && y != NULL);
}
/* Tampered leaf: flip a byte in the middle of the DER, expect reject.
* (Copy first — the KAT arrays are const.) */
{
static uint8_t bad[sizeof kat_rsa_leaf];
memcpy(bad, kat_rsa_leaf, sizeof bad);
bad[sizeof bad / 2] ^= 0x01;
T_CHECK(wo_x509_verify_one(bad, sizeof bad,
kat_rsa_ca, sizeof kat_rsa_ca) == 0);
}
/* Truncated DER never over-reads, always rejects. */
T_CHECK(wo_x509_verify_one(kat_rsa_leaf, 10,
kat_rsa_ca, sizeof kat_rsa_ca) == 0);
/* Validity window (certs are valid 2020-01-01 .. 2030-01-01). */
T_CHECK(wo_x509_check_validity(kat_rsa_leaf, sizeof kat_rsa_leaf,
"20250101000000") == 1);
T_CHECK(wo_x509_check_validity(kat_rsa_leaf, sizeof kat_rsa_leaf,
"20190101000000") == 0); /* before */
T_CHECK(wo_x509_check_validity(kat_rsa_leaf, sizeof kat_rsa_leaf,
"20310101000000") == 0); /* after */
T_CHECK(wo_x509_check_validity(kat_ec_leaf, sizeof kat_ec_leaf,
"20250101000000") == 1);
}
return t_report("test_crypto");
}

193
runtime/test/x509_vectors.h Normal file
View file

@ -0,0 +1,193 @@
/* Generated by scratchpad/gen_x509.py — python cryptography 41.0.7.
* Two real chains: RSA CA+leaf (SHA256withRSA), EC P-256 CA+leaf
* (ecdsa-with-SHA256). Vectors for the wo_x509 phase-E KAT. */
static const uint8_t kat_rsa_ca[] = {
0x30,0x82,0x02,0xc9,0x30,0x82,0x01,0xb1,0xa0,0x03,0x02,0x01,
0x02,0x02,0x14,0x30,0x0b,0xd4,0x57,0x1a,0xd0,0xc8,0x0f,0xe9,
0x12,0xb3,0x16,0x63,0x7a,0x5c,0xc3,0xe9,0xb0,0xfa,0x6e,0x30,
0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,
0x05,0x00,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,
0x03,0x0c,0x09,0x77,0x6f,0x2d,0x72,0x73,0x61,0x2d,0x63,0x61,
0x30,0x1e,0x17,0x0d,0x32,0x30,0x30,0x31,0x30,0x31,0x30,0x30,
0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x33,0x30,0x30,0x31,0x30,
0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x14,0x31,0x12,
0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x0c,0x09,0x77,0x6f,0x2d,
0x72,0x73,0x61,0x2d,0x63,0x61,0x30,0x82,0x01,0x22,0x30,0x0d,
0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,
0x01,0x01,0x00,0xbd,0x1a,0x09,0xfd,0x87,0xdb,0xfc,0xe6,0x45,
0xcb,0x1f,0x6b,0xbf,0x6e,0x83,0xbb,0x76,0x9c,0x0e,0x0d,0xeb,
0x95,0x58,0x7a,0x7a,0x4c,0xd5,0x16,0xf8,0x2d,0x52,0xe9,0xb9,
0xe0,0x71,0xdd,0xc9,0x65,0x01,0x5a,0x06,0x9c,0x29,0x9d,0x1f,
0xe2,0x32,0x12,0x99,0x57,0xc0,0xb9,0x5c,0x0d,0x0c,0x60,0x72,
0xe1,0x6d,0x45,0x23,0x22,0xed,0x6a,0x45,0x16,0x55,0x75,0x69,
0xfd,0x7e,0x0b,0xa3,0x6e,0xfd,0xb1,0x24,0x35,0x77,0xa4,0xde,
0x54,0x0f,0xb5,0xeb,0xc9,0x13,0xad,0x1b,0x15,0x58,0x75,0xde,
0xb6,0xb7,0x57,0x19,0x54,0x11,0x19,0xa5,0x72,0x09,0xf1,0x06,
0xdf,0x24,0xba,0x9a,0x74,0x3b,0x3d,0x8e,0xa6,0xa4,0xd7,0x52,
0xd3,0x32,0xd4,0x21,0xad,0xec,0xb7,0xce,0x9b,0xef,0x11,0x44,
0x84,0x67,0x5c,0x8e,0x0e,0xae,0xc9,0x26,0x01,0x75,0x18,0x52,
0x63,0x86,0x9b,0x31,0x89,0xdd,0x8f,0x06,0x96,0x07,0xd2,0x5b,
0x8d,0x1a,0xc1,0x33,0x43,0x53,0x59,0xde,0x45,0xfb,0xb0,0x83,
0x67,0xb8,0x63,0x6d,0x34,0x2e,0x87,0x4a,0xe4,0x70,0x03,0x9f,
0x24,0x46,0x86,0x8e,0x0e,0x55,0xa6,0x27,0xea,0xf1,0x03,0x84,
0x8e,0xbc,0x49,0xfc,0x92,0x0b,0x7f,0xf7,0x9a,0xb4,0x87,0xc1,
0x01,0x7c,0x64,0xd6,0x0f,0xe3,0x4e,0xcd,0x39,0xe2,0xb3,0xcb,
0xb1,0x33,0x4b,0xbe,0x98,0x78,0x49,0xb3,0x9b,0x08,0x73,0x20,
0x9e,0x4a,0xdc,0x3d,0x16,0xb6,0xb1,0x9f,0xc6,0xe3,0x1c,0x8a,
0xfc,0xaa,0x17,0x68,0x41,0x58,0x9d,0x84,0x00,0xc9,0x67,0x57,
0x9b,0xc7,0x01,0x3e,0x63,0x5b,0x4d,0x02,0x03,0x01,0x00,0x01,
0xa3,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,
0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x0d,0x06,
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,
0x03,0x82,0x01,0x01,0x00,0x9d,0x80,0x33,0xbe,0xf2,0x17,0x6b,
0x3d,0xb2,0x70,0xa3,0x5a,0x0e,0xc1,0xc8,0x8f,0xa2,0x08,0x1e,
0x57,0x60,0x4e,0x4d,0xfe,0x8c,0xab,0x13,0x03,0x47,0x9d,0x28,
0x51,0x9e,0x16,0x0e,0x48,0xdf,0xa2,0x55,0xf9,0x20,0x8f,0x58,
0xb6,0x4d,0x35,0x05,0x2e,0x01,0x46,0x35,0xf8,0x9a,0x4c,0x28,
0xad,0x28,0x6a,0x26,0x0e,0x42,0xba,0x7b,0x32,0xbb,0x04,0x9d,
0x23,0xec,0xea,0x14,0xb3,0x1f,0x77,0x28,0x76,0x74,0x74,0x97,
0x96,0x87,0x2c,0xeb,0x6f,0xb8,0xf5,0x1d,0x21,0x0e,0xe6,0x98,
0x41,0x72,0x8c,0x21,0x87,0xc9,0xc4,0x76,0x86,0x9f,0xea,0x96,
0x5f,0x74,0xea,0x0e,0x78,0x39,0xf9,0x8c,0x4b,0xc0,0x96,0xb3,
0xce,0x12,0x3b,0x80,0xf4,0x08,0xee,0x07,0xf0,0x96,0x9a,0x51,
0xe7,0x26,0xfb,0x6a,0x62,0x00,0x55,0x76,0xa4,0x1b,0x71,0xf0,
0x82,0x44,0x47,0x6d,0x28,0x3e,0x01,0xf7,0x03,0x64,0x59,0xae,
0xfc,0xc3,0x40,0x9e,0x36,0x60,0x04,0x68,0x7a,0xb8,0xcf,0x23,
0x0b,0x68,0x8e,0x1d,0xd4,0xd2,0xbe,0xc4,0xb1,0xbd,0x26,0x9a,
0x62,0x8c,0x38,0x67,0xd5,0x06,0x3b,0x64,0x6a,0x29,0x18,0x3d,
0x97,0x16,0x51,0x77,0x99,0xac,0x15,0x23,0x15,0xce,0x8e,0xe1,
0x04,0xcf,0xe3,0x83,0xc6,0xca,0xaf,0x49,0x37,0x31,0x31,0xfc,
0x4f,0x2b,0xe6,0xd7,0xd8,0xcf,0xbf,0x13,0x26,0xba,0x63,0x3d,
0x56,0xce,0xde,0x16,0x2c,0x06,0x47,0xf5,0xaa,0x30,0x3a,0xb1,
0x27,0x9d,0x7a,0xa9,0xeb,0x6f,0xd4,0x6b,0x1b,0x3d,0x6e,0x3c,
0x3d,0x54,0xa3,0x4e,0x1d,0xe7,0x0b,0xc4,0x04,
};
static const uint8_t kat_rsa_leaf[] = {
0x30,0x82,0x02,0xdc,0x30,0x82,0x01,0xc4,0xa0,0x03,0x02,0x01,
0x02,0x02,0x14,0x54,0x5e,0x84,0x52,0x6c,0xc6,0x6c,0x8c,0xd2,
0x5e,0x65,0x87,0x03,0xeb,0x62,0x96,0x80,0x26,0x7f,0x9a,0x30,
0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,
0x05,0x00,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,
0x03,0x0c,0x09,0x77,0x6f,0x2d,0x72,0x73,0x61,0x2d,0x63,0x61,
0x30,0x1e,0x17,0x0d,0x32,0x30,0x30,0x31,0x30,0x31,0x30,0x30,
0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x33,0x30,0x30,0x31,0x30,
0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x1b,0x31,0x19,
0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x0c,0x10,0x6c,0x65,0x61,
0x66,0x2e,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,
0x6d,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,
0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xd7,0x4f,
0x77,0x85,0xd8,0x35,0x2d,0x2c,0xc4,0x6e,0xd2,0x34,0xfe,0xcb,
0x46,0x8d,0xc1,0xb0,0x75,0xff,0x48,0xff,0x06,0x26,0x78,0x6b,
0xf5,0x71,0x42,0x74,0x12,0x89,0x2f,0x73,0xbb,0x11,0xc4,0x6a,
0xa1,0xc4,0x3e,0x24,0xb6,0x91,0xe7,0xe1,0x77,0xfa,0xe8,0xac,
0xd3,0xae,0x5b,0x72,0x3d,0x41,0xc1,0xe7,0x5d,0x8d,0xe9,0xc5,
0x1d,0xcd,0x43,0x9b,0xa3,0xc4,0x9e,0x5e,0x69,0x55,0x11,0x6d,
0x3a,0xa2,0x31,0x3b,0xcc,0xcf,0xa6,0x83,0x3c,0x21,0x46,0x64,
0x83,0xc4,0x25,0xb4,0xa2,0x52,0xb5,0xbe,0x86,0xaf,0xbc,0x64,
0xb2,0x92,0x56,0x49,0xc4,0x77,0x80,0x59,0xfd,0x44,0x62,0x79,
0xa3,0x04,0xdd,0x3c,0x5a,0xa8,0xe1,0x83,0x6e,0xae,0x50,0x5a,
0xf2,0x0f,0x37,0xbc,0xcc,0x7b,0x7b,0x95,0x6b,0x32,0xa2,0x21,
0x6b,0xd8,0x30,0x11,0xfd,0xa9,0x8c,0xbf,0xa4,0xb5,0xc3,0xb0,
0xe6,0x76,0x16,0x4a,0xac,0x1d,0x5b,0x38,0x4e,0xd5,0xc4,0xe5,
0x8e,0x6e,0x7d,0x05,0x9f,0x12,0xb9,0x36,0x38,0xe3,0x8f,0xfe,
0x4b,0x1e,0x48,0x49,0x73,0x80,0x74,0x5e,0xe3,0x0e,0xe1,0x20,
0x8f,0xb2,0xed,0xdf,0xe3,0x81,0x2b,0x29,0xab,0x22,0xdc,0x00,
0x35,0xf2,0xc0,0x22,0xd9,0xfd,0xc5,0x25,0xa3,0x6d,0x54,0x88,
0x50,0x77,0x73,0xff,0x95,0x1a,0x70,0x93,0x2d,0x89,0x59,0xb5,
0x83,0x49,0x6d,0x55,0x2b,0x34,0x08,0x83,0x0e,0xd6,0x3c,0x7a,
0x2a,0x42,0x22,0xe8,0x6d,0x9d,0x68,0x2d,0x06,0xfc,0x6c,0xf8,
0x36,0x49,0xa1,0x8a,0x43,0x2f,0x88,0x59,0x14,0x31,0x95,0x8f,
0xa4,0x85,0x02,0x03,0x01,0x00,0x01,0xa3,0x1f,0x30,0x1d,0x30,
0x1b,0x06,0x03,0x55,0x1d,0x11,0x04,0x14,0x30,0x12,0x82,0x10,
0x6c,0x65,0x61,0x66,0x2e,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,
0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,
0xb5,0xb0,0xfb,0xf6,0xb6,0x5c,0x1c,0xfa,0xcc,0xf9,0xcb,0x81,
0xc0,0xa6,0x12,0x5f,0xe7,0xb4,0x12,0x31,0x22,0x93,0xd8,0xcd,
0x98,0xc9,0x7a,0xbe,0xeb,0x1f,0x95,0x42,0x59,0x1c,0x38,0xe9,
0x0a,0x44,0x5d,0x85,0x92,0x9e,0xbc,0xdf,0x51,0x72,0x2c,0xe8,
0xbb,0xd8,0x55,0x16,0xcf,0xd6,0xe1,0xed,0x39,0x91,0x44,0x91,
0xc7,0x9e,0xa7,0x53,0x0a,0xe2,0x60,0x57,0xdb,0xee,0x9e,0xd4,
0xa5,0x75,0x59,0x92,0xa3,0xb1,0xb3,0xfc,0xaf,0x35,0x32,0xe0,
0xba,0xec,0xff,0xd5,0x4a,0x44,0x33,0x63,0xb8,0xbc,0x27,0x16,
0x4e,0xb7,0x5e,0xaa,0xb3,0xa9,0xb2,0x06,0x14,0x4f,0xa1,0x65,
0xc4,0x8e,0x0f,0x4a,0x46,0x2f,0xbb,0xed,0xb0,0x73,0xd6,0x8d,
0x96,0x23,0x92,0xbe,0xe8,0x55,0xac,0x6a,0xbc,0xb7,0x70,0xbd,
0x64,0xa5,0xe4,0xf4,0xf0,0x1a,0xd8,0xba,0xf1,0x4f,0x8e,0x8b,
0x64,0x6f,0x4e,0xf1,0x60,0xe5,0xd3,0x5a,0x4f,0x9c,0xd8,0x01,
0x72,0xc8,0x5e,0x70,0x7f,0x13,0xf0,0x0c,0x94,0x27,0x65,0x3e,
0xe0,0x07,0x02,0x4a,0x14,0x67,0x02,0x9d,0xbc,0x38,0xc7,0x9b,
0xf0,0x70,0xf5,0x87,0x2e,0x1b,0xaf,0xe1,0x81,0xeb,0x20,0xac,
0xd1,0x34,0x0e,0x20,0x42,0xa4,0xe7,0xeb,0x0a,0x75,0x3d,0x94,
0x48,0x48,0x69,0x81,0xf8,0x1f,0x36,0x0a,0xdf,0xd5,0xd8,0xec,
0x1d,0x76,0xa3,0xda,0x02,0xad,0xe0,0x31,0xa1,0xa0,0x4e,0xe8,
0xe7,0x67,0xdf,0x1b,0x95,0x93,0x2d,0x01,0x5b,0x4a,0x5b,0xd6,
0x60,0xdc,0xbf,0x96,0x09,0x28,0x0c,0x91,0xe0,0x09,0x71,0xfd,
0xf7,0x24,0x40,0xd3,
};
static const uint8_t kat_ec_ca[] = {
0x30,0x82,0x01,0x3a,0x30,0x81,0xe1,0xa0,0x03,0x02,0x01,0x02,
0x02,0x14,0x15,0x18,0x99,0x87,0xb5,0xee,0xa4,0x33,0x55,0x4f,
0x83,0x91,0x2d,0xdd,0xa7,0x30,0x19,0xa9,0xfa,0x12,0x30,0x0a,
0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02,0x30,0x13,
0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x03,0x0c,0x08,0x77,
0x6f,0x2d,0x65,0x63,0x2d,0x63,0x61,0x30,0x1e,0x17,0x0d,0x32,
0x30,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
0x17,0x0d,0x33,0x30,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
0x30,0x30,0x5a,0x30,0x13,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,
0x04,0x03,0x0c,0x08,0x77,0x6f,0x2d,0x65,0x63,0x2d,0x63,0x61,
0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,
0x01,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,
0x42,0x00,0x04,0x0b,0xfc,0x3f,0x30,0x5a,0x4d,0x6a,0x2c,0x7f,
0x37,0xab,0x50,0x56,0xc7,0xf5,0xcd,0x44,0x07,0xb8,0xbf,0xd0,
0xe6,0xff,0x3e,0x3d,0x50,0x13,0xcf,0xbc,0x2b,0x1b,0xff,0xde,
0xaf,0x80,0x84,0x99,0x6d,0xc2,0x1e,0x46,0x7e,0x16,0x0a,0x2d,
0x9e,0x13,0xd9,0xfb,0x35,0x33,0x4b,0x59,0x35,0x16,0x96,0x9d,
0x35,0x9f,0x96,0x7f,0x79,0x07,0xb1,0xa3,0x13,0x30,0x11,0x30,
0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,
0x03,0x01,0x01,0xff,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0xce,
0x3d,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21,0x00,
0xf8,0x45,0x9e,0x09,0xb9,0xe7,0xcd,0xe8,0x06,0xe9,0xd9,0x59,
0xcc,0x32,0x38,0x82,0xd6,0x84,0x07,0x95,0xc5,0x2a,0x17,0x03,
0x51,0xd8,0xb8,0xa0,0xd9,0x49,0x5c,0x90,0x02,0x20,0x36,0x9a,
0x8a,0x32,0x27,0xe5,0x47,0xf1,0x7c,0x06,0xb1,0xd1,0x5f,0xc7,
0xe1,0x00,0x68,0xe4,0x80,0xe1,0x14,0xea,0xbb,0x57,0x60,0xfc,
0xfa,0xb5,0xd2,0xe0,0x5d,0xcb,
};
static const uint8_t kat_ec_leaf[] = {
0x30,0x82,0x01,0x4e,0x30,0x81,0xf5,0xa0,0x03,0x02,0x01,0x02,
0x02,0x14,0x21,0xcc,0xa6,0xdd,0x2d,0x8a,0xb5,0xf6,0xf6,0x5e,
0x26,0x25,0x9d,0x7f,0xef,0x1b,0xf5,0xe7,0xc7,0x97,0x30,0x0a,
0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02,0x30,0x13,
0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x03,0x0c,0x08,0x77,
0x6f,0x2d,0x65,0x63,0x2d,0x63,0x61,0x30,0x1e,0x17,0x0d,0x32,
0x30,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
0x17,0x0d,0x33,0x30,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
0x30,0x30,0x5a,0x30,0x1b,0x31,0x19,0x30,0x17,0x06,0x03,0x55,
0x04,0x03,0x0c,0x10,0x6c,0x65,0x61,0x66,0x2e,0x65,0x78,0x61,
0x6d,0x70,0x6c,0x65,0x2e,0x6f,0x72,0x67,0x30,0x59,0x30,0x13,
0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,
0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xc5,
0xb1,0x2b,0x08,0x10,0xdf,0x26,0x4a,0xd8,0x1d,0x2f,0x43,0x89,
0xca,0xf5,0x8e,0x8a,0x0e,0xdd,0x39,0xbd,0x8e,0xe4,0x75,0x8e,
0x84,0x9a,0x77,0xd4,0xc5,0x51,0x16,0x46,0x9a,0x22,0x0b,0x2f,
0x0e,0x17,0xc7,0x56,0x3c,0xfe,0x38,0xd1,0xd4,0xc4,0x60,0xef,
0x87,0xb1,0x4a,0x34,0x34,0xc5,0xa8,0x2c,0x42,0x31,0xde,0xfb,
0x0c,0x0d,0x29,0xa3,0x1f,0x30,0x1d,0x30,0x1b,0x06,0x03,0x55,
0x1d,0x11,0x04,0x14,0x30,0x12,0x82,0x10,0x6c,0x65,0x61,0x66,
0x2e,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x2e,0x6f,0x72,0x67,
0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02,
0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x08,0x96,0x01,0xfd,0x5e,
0x88,0x5d,0x9e,0x0a,0x6d,0xbd,0xcf,0xb7,0xe0,0x3f,0xc3,0xc4,
0xf1,0x6b,0x40,0xc9,0x7c,0x10,0x3f,0xdd,0x83,0x4b,0xca,0x5a,
0x60,0xdd,0x36,0x02,0x21,0x00,0x85,0x01,0x87,0x86,0xa5,0x6d,
0x05,0xc9,0x6f,0x42,0xb5,0xdf,0x7a,0xbb,0x32,0x06,0x08,0x75,
0x40,0x32,0xc2,0x33,0xe4,0x62,0xe5,0xd7,0x9c,0x39,0xee,0xd3,
0xc1,0x1c,
};