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:
parent
9d1689be55
commit
5f5d774d76
5 changed files with 579 additions and 0 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
67
runtime/test/gen_x509.py
Normal 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)))
|
||||
|
|
@ -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
193
runtime/test/x509_vectors.h
Normal 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,
|
||||
};
|
||||
|
||||
Loading…
Reference in a new issue