/* Automatically generated code; do not modify directly. */ #include #include typedef struct { uint32_t *dp; uint32_t *rp; const unsigned char *ip; } t0_context; static uint32_t t0_parse7E_unsigned(const unsigned char **p) { uint32_t x; x = 0; for (;;) { unsigned y; y = *(*p) ++; x = (x << 7) | (uint32_t)(y & 0x7F); if (y < 0x80) { return x; } } } static int32_t t0_parse7E_signed(const unsigned char **p) { int neg; uint32_t x; neg = ((**p) >> 6) & 1; x = (uint32_t)-neg; for (;;) { unsigned y; y = *(*p) ++; x = (x << 7) | (uint32_t)(y & 0x7F); if (y < 0x80) { if (neg) { return -(int32_t)~x - 1; } else { return (int32_t)x; } } } } #define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) #define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) #define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) #define T0_INT1(x) T0_FBYTE(x, 0) #define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) #define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) #define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) #define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) /* static const unsigned char t0_datablock[]; */ void br_x509_minimal_init_main(void *t0ctx); void br_x509_minimal_run(void *t0ctx); #include "inner.h" #include "inner.h" /* * Implementation Notes * -------------------- * * The C code pushes the data by chunks; all decoding is done in the * T0 code. The cert_length value is set to the certificate length when * a new certificate is started; the T0 code picks it up as outer limit, * and decoding functions use it to ensure that no attempt is made at * reading past it. The T0 code also checks that once the certificate is * decoded, there are no trailing bytes. * * The T0 code sets cert_length to 0 when the certificate is fully * decoded. * * The C code must still perform two checks: * * -- If the certificate length is 0, then the T0 code will not be * invoked at all. This invalid condition must thus be reported by the * C code. * * -- When reaching the end of certificate, the C code must verify that * the certificate length has been set to 0, thereby signaling that * the T0 code properly decoded a certificate. * * Processing of a chain works in the following way: * * -- The error flag is set to a non-zero value when validation is * finished. The value is either BR_ERR_X509_OK (validation is * successful) or another non-zero error code. When a non-zero error * code is obtained, the remaining bytes in the current certificate and * the subsequent certificates (if any) are completely ignored. * * -- Each certificate is decoded in due course, with the following * "interesting points": * * -- Start of the TBS: the multihash engine is reset and activated. * * -- Start of the issuer DN: the secondary hash engine is started, * to process the encoded issuer DN. * * -- End of the issuer DN: the secondary hash engine is stopped. The * resulting hash value is computed and then copied into the * next_dn_hash[] buffer. * * -- Start of the subject DN: the secondary hash engine is started, * to process the encoded subject DN. * * -- For the EE certificate only: the Common Name, if any, is matched * against the expected server name. * * -- End of the subject DN: the secondary hash engine is stopped. The * resulting hash value is computed into the pad. It is then processed: * * -- If this is the EE certificate, then the hash is ignored * (except for direct trust processing, see later; the hash is * simply left in current_dn_hash[]). * * -- Otherwise, the hashed subject DN is compared with the saved * hash value (in saved_dn_hash[]). They must match. * * Either way, the next_dn_hash[] value is then copied into the * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[] * contains the hash of the issuer DN for the current certificate, * and current_dn_hash[] contains the hash of the subject DN for the * current certificate. * * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown * key types are reported at that point. * * -- If this is the EE certificate, then the key type is compared * with the expected key type (initialization parameter). The public * key data is copied to ee_pkey_data[]. The key and hashed subject * DN are also compared with the "direct trust" keys; if the key * and DN are matched, then validation ends with a success. * * -- Otherwise, the saved signature (cert_sig[]) is verified * against the saved TBS hash (tbs_hash[]) and that freshly * decoded public key. Failure here ends validation with an error. * * -- Extensions: extension values are processed in due order. * * -- Basic Constraints: for all certificates except EE, must be * present, indicate a CA, and have a path length compatible with * the chain length so far. * * -- Key Usage: for the EE, if present, must allow signatures * or encryption/key exchange, as required for the cipher suite. * For non-EE, if present, must have the "certificate sign" bit. * * -- Subject Alt Name: for the EE, dNSName names are matched * against the server name. Ignored for non-EE. * * -- Authority Key Identifier, Subject Key Identifier, Issuer * Alt Name, Subject Directory Attributes, CRL Distribution Points * Freshest CRL, Authority Info Access and Subject Info Access * extensions are always ignored: they either contain only * informative data, or they relate to revocation processing, which * we explicitly do not support. * * -- All other extensions are ignored if non-critical. If a * critical extension other than the ones above is encountered, * then a failure is reported. * * -- End of the TBS: the multihash engine is stopped. * * -- Signature algorithm: the signature algorithm on the * certificate is decoded. A failure is reported if that algorithm * is unknown. The hashed TBS corresponding to the signature hash * function is computed and stored in tbs_hash[] (if not supported, * then a failure is reported). The hash OID and length are stored * in cert_sig_hash_oid and cert_sig_hash_len. * * -- Signature value: the signature value is copied into the * cert_sig[] array. * * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is * looked up in the trust store (CA trust anchors only); for all * that match, the signature (cert_sig[]) is verified against the * anchor public key (hashed TBS is in tbs_hash[]). If one of these * signatures is valid, then validation ends with a success. * * -- If the chain end is reached without obtaining a validation success, * then validation is reported as failed. */ #if BR_USE_UNIX_TIME #include #endif #if BR_USE_WIN32_TIME #include #endif /* * The T0 compiler will produce these prototypes declarations in the * header. * void br_x509_minimal_init_main(void *ctx); void br_x509_minimal_run(void *ctx); */ /* see bearssl_x509.h */ void br_x509_minimal_init(br_x509_minimal_context *ctx, const br_hash_class *dn_hash_impl, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) { memset(ctx, 0, sizeof *ctx); ctx->vtable = &br_x509_minimal_vtable; ctx->dn_hash_impl = dn_hash_impl; ctx->trust_anchors = trust_anchors; ctx->trust_anchors_num = trust_anchors_num; } static void xm_start_chain(const br_x509_class **ctx, const char *server_name) { br_x509_minimal_context *cc; size_t u; cc = (br_x509_minimal_context *)(void *)ctx; for (u = 0; u < cc->num_name_elts; u ++) { cc->name_elts[u].status = 0; cc->name_elts[u].buf[0] = 0; } memset(&cc->pkey, 0, sizeof cc->pkey); cc->num_certs = 0; cc->err = 0; cc->cpu.dp = cc->dp_stack; cc->cpu.rp = cc->rp_stack; br_x509_minimal_init_main(&cc->cpu); if (server_name == NULL || *server_name == 0) { cc->server_name = NULL; } else { cc->server_name = server_name; } } static void xm_start_cert(const br_x509_class **ctx, uint32_t length) { br_x509_minimal_context *cc; cc = (br_x509_minimal_context *)(void *)ctx; if (cc->err != 0) { return; } if (length == 0) { cc->err = BR_ERR_X509_TRUNCATED; return; } cc->cert_length = length; } static void xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) { br_x509_minimal_context *cc; cc = (br_x509_minimal_context *)(void *)ctx; if (cc->err != 0) { return; } cc->hbuf = buf; cc->hlen = len; br_x509_minimal_run(&cc->cpu); } static void xm_end_cert(const br_x509_class **ctx) { br_x509_minimal_context *cc; cc = (br_x509_minimal_context *)(void *)ctx; if (cc->err == 0 && cc->cert_length != 0) { cc->err = BR_ERR_X509_TRUNCATED; } cc->num_certs ++; } static unsigned xm_end_chain(const br_x509_class **ctx) { br_x509_minimal_context *cc; cc = (br_x509_minimal_context *)(void *)ctx; if (cc->err == 0) { if (cc->num_certs == 0) { cc->err = BR_ERR_X509_EMPTY_CHAIN; } else { cc->err = BR_ERR_X509_NOT_TRUSTED; } } else if (cc->err == BR_ERR_X509_OK) { return 0; } return (unsigned)cc->err; } static const br_x509_pkey * xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages) { br_x509_minimal_context *cc; cc = (br_x509_minimal_context *)(void *)ctx; if (cc->err == BR_ERR_X509_OK || cc->err == BR_ERR_X509_NOT_TRUSTED) { if (usages != NULL) { *usages = cc->key_usages; } return &((br_x509_minimal_context *)(void *)ctx)->pkey; } else { return NULL; } } /* see bearssl_x509.h */ const br_x509_class br_x509_minimal_vtable = { sizeof(br_x509_minimal_context), xm_start_chain, xm_start_cert, xm_append, xm_end_cert, xm_end_chain, xm_get_pkey }; #define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu))) #define CONTEXT_NAME br_x509_minimal_context #define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK) /* * Hash a DN (from a trust anchor) into the provided buffer. This uses the * DN hash implementation and context structure from the X.509 engine * context. */ static void hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len, unsigned char *out) { ctx->dn_hash_impl->init(&ctx->dn_hash.vtable); ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len); ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out); } /* * Compare two big integers for equality. The integers use unsigned big-endian * encoding; extra leading bytes (of value 0) are allowed. */ static int eqbigint(const unsigned char *b1, size_t len1, const unsigned char *b2, size_t len2) { while (len1 > 0 && *b1 == 0) { b1 ++; len1 --; } while (len2 > 0 && *b2 == 0) { b2 ++; len2 --; } if (len1 != len2) { return 0; } return memcmp(b1, b2, len1) == 0; } /* * Compare two strings for equality, in a case-insensitive way. This * function handles casing only for ASCII letters. */ static int eqnocase(const void *s1, const void *s2, size_t len) { const unsigned char *buf1, *buf2; buf1 = s1; buf2 = s2; while (len -- > 0) { int x1, x2; x1 = *buf1 ++; x2 = *buf2 ++; if (x1 >= 'A' && x1 <= 'Z') { x1 += 'a' - 'A'; } if (x2 >= 'A' && x2 <= 'Z') { x2 += 'a' - 'A'; } if (x1 != x2) { return 0; } } return 1; } static int verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk); static const unsigned char t0_datablock[] = { 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04, 0x03, 0x55, 0x04, 0x03, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, 0x0F, 0x1F, 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, 0x26, 0x1E, 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, 0x0F, 0x3F, 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, 0x26, 0x3E, 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13, 0x03, 0x55, 0x1D, 0x0F, 0x03, 0x55, 0x1D, 0x11, 0x03, 0x55, 0x1D, 0x20, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x03, 0x55, 0x1D, 0x23, 0x03, 0x55, 0x1D, 0x0E, 0x03, 0x55, 0x1D, 0x12, 0x03, 0x55, 0x1D, 0x09, 0x03, 0x55, 0x1D, 0x1F, 0x03, 0x55, 0x1D, 0x2E, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0B }; static const unsigned char t0_codeblock[] = { 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_DN), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_SERVER_NAME), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_CRITICAL_EXTENSION), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_DN_MISMATCH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_EXPIRED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_FORBIDDEN_KEY_USAGE), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_NOT_CA), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_len)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_oid)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_usages)), 0x00, 0x00, 0x01, T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01, T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00, 0x00, 0x01, 0x81, 0x02, 0x00, 0x00, 0x8F, 0x05, 0x05, 0x33, 0x41, 0x01, 0x00, 0x00, 0x33, 0x01, 0x0A, 0x0E, 0x09, 0x01, 0x9A, 0xFF, 0xB8, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x82, 0x19, 0x00, 0x00, 0x01, 0x82, 0x01, 0x00, 0x00, 0x01, 0x81, 0x68, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x26, 0x02, 0x01, 0x13, 0x3A, 0x02, 0x00, 0x0F, 0x15, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x05, 0x02, 0x51, 0x29, 0x00, 0x00, 0x06, 0x02, 0x52, 0x29, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x00, 0x11, 0x05, 0x02, 0x55, 0x29, 0x71, 0x00, 0x00, 0x11, 0x05, 0x02, 0x55, 0x29, 0x72, 0x00, 0x00, 0x06, 0x02, 0x4B, 0x29, 0x00, 0x00, 0x01, 0x82, 0x11, 0x00, 0x00, 0x26, 0x21, 0x01, 0x08, 0x0E, 0x3A, 0x3F, 0x21, 0x09, 0x00, 0x0B, 0x03, 0x00, 0x5A, 0x2B, 0xAC, 0x38, 0xAC, 0xB0, 0x26, 0x01, 0x20, 0x11, 0x06, 0x11, 0x25, 0x71, 0xAA, 0xB0, 0x01, 0x02, 0x75, 0xAD, 0x01, 0x02, 0x12, 0x06, 0x02, 0x56, 0x29, 0x76, 0xB0, 0x01, 0x02, 0x75, 0xAB, 0xAC, 0xBF, 0x99, 0x64, 0x60, 0x22, 0x16, 0xAC, 0xA4, 0x03, 0x01, 0x03, 0x02, 0xA4, 0x02, 0x02, 0x02, 0x01, 0x19, 0x06, 0x02, 0x4A, 0x29, 0x76, 0x02, 0x00, 0x06, 0x05, 0x9A, 0x03, 0x03, 0x04, 0x09, 0x99, 0x60, 0x67, 0x22, 0x28, 0x05, 0x02, 0x49, 0x29, 0x67, 0x64, 0x22, 0x16, 0xAC, 0xAC, 0x9B, 0x05, 0x02, 0x56, 0x29, 0xB9, 0x27, 0x06, 0x27, 0xBF, 0xA1, 0xAC, 0x62, 0xA7, 0x03, 0x05, 0x62, 0x3A, 0x02, 0x05, 0x09, 0x3A, 0x02, 0x05, 0x0A, 0xA7, 0x03, 0x06, 0x76, 0x63, 0x2A, 0x01, 0x81, 0x00, 0x09, 0x02, 0x05, 0x12, 0x06, 0x02, 0x57, 0x29, 0x76, 0x59, 0x03, 0x04, 0x04, 0x3A, 0x85, 0x27, 0x06, 0x34, 0x9B, 0x05, 0x02, 0x56, 0x29, 0x68, 0x27, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x69, 0x27, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A, 0x6A, 0x27, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x56, 0x29, 0x03, 0x07, 0x76, 0xA1, 0x26, 0x03, 0x08, 0x26, 0x62, 0x33, 0x0D, 0x06, 0x02, 0x4F, 0x29, 0xA2, 0x58, 0x03, 0x04, 0x04, 0x02, 0x56, 0x29, 0x76, 0x02, 0x00, 0x06, 0x21, 0x02, 0x04, 0x59, 0x30, 0x11, 0x06, 0x08, 0x25, 0x02, 0x05, 0x02, 0x06, 0x1E, 0x04, 0x10, 0x58, 0x30, 0x11, 0x06, 0x08, 0x25, 0x02, 0x07, 0x02, 0x08, 0x1D, 0x04, 0x03, 0x56, 0x29, 0x25, 0x04, 0x24, 0x02, 0x04, 0x59, 0x30, 0x11, 0x06, 0x08, 0x25, 0x02, 0x05, 0x02, 0x06, 0x24, 0x04, 0x10, 0x58, 0x30, 0x11, 0x06, 0x08, 0x25, 0x02, 0x07, 0x02, 0x08, 0x23, 0x04, 0x03, 0x56, 0x29, 0x25, 0x26, 0x06, 0x01, 0x29, 0x25, 0x01, 0x00, 0x03, 0x09, 0xB1, 0x01, 0x21, 0x8C, 0x01, 0x22, 0x8C, 0x26, 0x01, 0x23, 0x11, 0x06, 0x81, 0x26, 0x25, 0x71, 0xAA, 0xAC, 0x26, 0x06, 0x81, 0x1A, 0x01, 0x00, 0x03, 0x0A, 0xAC, 0x9B, 0x25, 0xB0, 0x26, 0x01, 0x01, 0x11, 0x06, 0x04, 0xA3, 0x03, 0x0A, 0xB0, 0x01, 0x04, 0x75, 0xAA, 0x6E, 0x27, 0x06, 0x0F, 0x02, 0x00, 0x06, 0x03, 0xC0, 0x04, 0x05, 0x96, 0x01, 0x7F, 0x03, 0x09, 0x04, 0x80, 0x6C, 0x8E, 0x27, 0x06, 0x06, 0x02, 0x00, 0x98, 0x04, 0x80, 0x62, 0xC2, 0x27, 0x06, 0x11, 0x02, 0x00, 0x06, 0x09, 0x01, 0x00, 0x03, 0x03, 0x95, 0x03, 0x03, 0x04, 0x01, 0xC0, 0x04, 0x80, 0x4D, 0x70, 0x27, 0x06, 0x0A, 0x02, 0x0A, 0x06, 0x03, 0x97, 0x04, 0x01, 0xC0, 0x04, 0x3F, 0x6D, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x38, 0xC5, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x31, 0x8D, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x2A, 0xC3, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x23, 0x77, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x1C, 0x82, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x15, 0x6C, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x0E, 0xC4, 0x27, 0x06, 0x03, 0xC0, 0x04, 0x07, 0x02, 0x0A, 0x06, 0x02, 0x48, 0x29, 0xC0, 0x76, 0x76, 0x04, 0xFE, 0x62, 0x76, 0x76, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x55, 0x29, 0x25, 0x76, 0x39, 0x02, 0x00, 0x06, 0x08, 0x02, 0x03, 0x3B, 0x2F, 0x05, 0x02, 0x44, 0x29, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00, 0x02, 0x09, 0x2F, 0x05, 0x02, 0x50, 0x29, 0xB0, 0x73, 0xAA, 0x9B, 0x06, 0x80, 0x77, 0xBA, 0x27, 0x06, 0x07, 0x01, 0x02, 0x59, 0x87, 0x04, 0x80, 0x5E, 0xBB, 0x27, 0x06, 0x07, 0x01, 0x03, 0x59, 0x88, 0x04, 0x80, 0x53, 0xBC, 0x27, 0x06, 0x07, 0x01, 0x04, 0x59, 0x89, 0x04, 0x80, 0x48, 0xBD, 0x27, 0x06, 0x06, 0x01, 0x05, 0x59, 0x8A, 0x04, 0x3E, 0xBE, 0x27, 0x06, 0x06, 0x01, 0x06, 0x59, 0x8B, 0x04, 0x34, 0x7C, 0x27, 0x06, 0x06, 0x01, 0x02, 0x58, 0x87, 0x04, 0x2A, 0x7D, 0x27, 0x06, 0x06, 0x01, 0x03, 0x58, 0x88, 0x04, 0x20, 0x7E, 0x27, 0x06, 0x06, 0x01, 0x04, 0x58, 0x89, 0x04, 0x16, 0x7F, 0x27, 0x06, 0x06, 0x01, 0x05, 0x58, 0x8A, 0x04, 0x0C, 0x80, 0x27, 0x06, 0x06, 0x01, 0x06, 0x58, 0x8B, 0x04, 0x02, 0x56, 0x29, 0x5D, 0x34, 0x5F, 0x36, 0x1C, 0x26, 0x05, 0x02, 0x56, 0x29, 0x5C, 0x36, 0x04, 0x02, 0x56, 0x29, 0xBF, 0xA1, 0x26, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x4F, 0x29, 0x26, 0x5E, 0x34, 0x5B, 0xA2, 0x76, 0x76, 0x01, 0x00, 0x5A, 0x35, 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x26, 0x01, 0x00, 0x01, 0x09, 0x6F, 0x05, 0x02, 0x47, 0x29, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x01, 0x81, 0x08, 0x00, 0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81, 0x19, 0x00, 0x00, 0x01, 0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00, 0x01, 0x7B, 0x01, 0x01, 0x11, 0x3A, 0x01, 0x83, 0xFD, 0x7F, 0x11, 0x15, 0x06, 0x03, 0x3A, 0x25, 0x00, 0x3A, 0x26, 0x03, 0x00, 0x26, 0xC6, 0x05, 0x04, 0x41, 0x01, 0x00, 0x00, 0x26, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x93, 0x04, 0x80, 0x49, 0x26, 0x01, 0x90, 0x00, 0x0D, 0x06, 0x0F, 0x01, 0x06, 0x14, 0x01, 0x81, 0x40, 0x2F, 0x93, 0x02, 0x00, 0x01, 0x00, 0x94, 0x04, 0x33, 0x26, 0x01, 0x83, 0xFF, 0x7F, 0x0D, 0x06, 0x14, 0x01, 0x0C, 0x14, 0x01, 0x81, 0x60, 0x2F, 0x93, 0x02, 0x00, 0x01, 0x06, 0x94, 0x02, 0x00, 0x01, 0x00, 0x94, 0x04, 0x17, 0x01, 0x12, 0x14, 0x01, 0x81, 0x70, 0x2F, 0x93, 0x02, 0x00, 0x01, 0x0C, 0x94, 0x02, 0x00, 0x01, 0x06, 0x94, 0x02, 0x00, 0x01, 0x00, 0x94, 0x00, 0x00, 0x01, 0x82, 0x15, 0x00, 0x00, 0x26, 0x01, 0x83, 0xB0, 0x00, 0x01, 0x83, 0xB7, 0x7F, 0x6F, 0x00, 0x00, 0x01, 0x81, 0x34, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x81, 0x78, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00, 0x01, 0x80, 0x43, 0x00, 0x00, 0x01, 0x80, 0x4D, 0x00, 0x00, 0x01, 0x80, 0x57, 0x00, 0x00, 0x01, 0x80, 0x61, 0x00, 0x00, 0x30, 0x11, 0x06, 0x04, 0x41, 0xAA, 0xBF, 0xB1, 0x00, 0x00, 0x01, 0x82, 0x09, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x26, 0x01, 0x83, 0xB8, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x6F, 0x00, 0x00, 0x01, 0x30, 0x61, 0x36, 0x01, 0x7F, 0x79, 0x1A, 0x01, 0x00, 0x79, 0x1A, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x38, 0x00, 0x01, 0x7B, 0x0D, 0x06, 0x02, 0x4E, 0x29, 0x26, 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x30, 0x26, 0x3E, 0x3A, 0x01, 0x82, 0x00, 0x13, 0x2F, 0x06, 0x04, 0x41, 0x01, 0x00, 0x00, 0x30, 0x66, 0x09, 0x36, 0x3F, 0x00, 0x00, 0x14, 0x01, 0x3F, 0x15, 0x01, 0x81, 0x00, 0x2F, 0x93, 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, 0xAC, 0x26, 0x06, 0x80, 0x59, 0xB0, 0x01, 0x20, 0x30, 0x11, 0x06, 0x17, 0x25, 0x71, 0xAA, 0x9B, 0x25, 0x01, 0x7F, 0x2E, 0x03, 0x01, 0xB0, 0x01, 0x20, 0x74, 0xAA, 0xAF, 0x02, 0x01, 0x20, 0x76, 0x76, 0x04, 0x38, 0x01, 0x21, 0x30, 0x11, 0x06, 0x08, 0x25, 0x72, 0xB3, 0x01, 0x01, 0x1F, 0x04, 0x2A, 0x01, 0x22, 0x30, 0x11, 0x06, 0x11, 0x25, 0x72, 0xB3, 0x26, 0x06, 0x06, 0x2C, 0x02, 0x00, 0x2F, 0x03, 0x00, 0x01, 0x02, 0x1F, 0x04, 0x13, 0x01, 0x26, 0x30, 0x11, 0x06, 0x08, 0x25, 0x72, 0xB3, 0x01, 0x06, 0x1F, 0x04, 0x05, 0x41, 0xAB, 0x01, 0x00, 0x25, 0x04, 0xFF, 0x23, 0x76, 0x02, 0x00, 0x00, 0x00, 0xAC, 0xB1, 0x26, 0x01, 0x01, 0x11, 0x06, 0x08, 0xA3, 0x05, 0x02, 0x50, 0x29, 0xB1, 0x04, 0x02, 0x50, 0x29, 0x26, 0x01, 0x02, 0x11, 0x06, 0x0C, 0x25, 0x72, 0xAD, 0x65, 0x2B, 0x40, 0x0D, 0x06, 0x02, 0x50, 0x29, 0xB1, 0x01, 0x7F, 0x10, 0x06, 0x02, 0x55, 0x29, 0x25, 0x76, 0x00, 0x00, 0xAC, 0x26, 0x06, 0x1A, 0xAC, 0x9B, 0x25, 0x26, 0x06, 0x11, 0xAC, 0x26, 0x06, 0x0C, 0xAC, 0x9B, 0x25, 0x86, 0x27, 0x05, 0x02, 0x48, 0x29, 0xBF, 0x04, 0x71, 0x76, 0x76, 0x04, 0x63, 0x76, 0x00, 0x02, 0x03, 0x00, 0xB0, 0x01, 0x03, 0x75, 0xAA, 0xB7, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02, 0x55, 0x29, 0x26, 0x01, 0x00, 0x30, 0x11, 0x06, 0x05, 0x25, 0x4C, 0x29, 0x04, 0x15, 0x01, 0x01, 0x30, 0x11, 0x06, 0x0A, 0x25, 0xB7, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E, 0x04, 0x05, 0x25, 0xB7, 0x01, 0x00, 0x25, 0x02, 0x00, 0x06, 0x19, 0x01, 0x00, 0x30, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01, 0x10, 0x2F, 0x3A, 0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2F, 0x61, 0x36, 0x04, 0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x4C, 0x29, 0xBF, 0x00, 0x00, 0x37, 0xAC, 0xBF, 0x1B, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x37, 0xAC, 0x26, 0x06, 0x30, 0xB0, 0x01, 0x11, 0x74, 0xAA, 0x26, 0x05, 0x02, 0x43, 0x29, 0x26, 0x06, 0x20, 0xAC, 0x9B, 0x25, 0x84, 0x27, 0x03, 0x01, 0x01, 0x00, 0x2E, 0x03, 0x02, 0xAF, 0x26, 0x02, 0x01, 0x15, 0x06, 0x07, 0x2C, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x02, 0x20, 0x76, 0x04, 0x5D, 0x76, 0x04, 0x4D, 0x76, 0x1B, 0x02, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x06, 0x75, 0xAE, 0x00, 0x00, 0xB5, 0x83, 0x06, 0x0E, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, 0x00, 0x01, 0x00, 0x00, 0xB5, 0x6B, 0x04, 0x08, 0x8F, 0x06, 0x05, 0x25, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0x83, 0x06, 0x0E, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, 0x00, 0x01, 0x00, 0x00, 0xB6, 0x6B, 0x04, 0x08, 0x8F, 0x06, 0x05, 0x25, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x00, 0x04, 0x80, 0x55, 0x26, 0x01, 0x81, 0x40, 0x0D, 0x06, 0x07, 0x25, 0x01, 0x00, 0x00, 0x04, 0x80, 0x47, 0x26, 0x01, 0x81, 0x60, 0x0D, 0x06, 0x0E, 0x01, 0x1F, 0x15, 0x01, 0x01, 0xA0, 0x01, 0x81, 0x00, 0x01, 0x8F, 0x7F, 0x04, 0x32, 0x26, 0x01, 0x81, 0x70, 0x0D, 0x06, 0x0F, 0x01, 0x0F, 0x15, 0x01, 0x02, 0xA0, 0x01, 0x90, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x04, 0x1C, 0x26, 0x01, 0x81, 0x78, 0x0D, 0x06, 0x11, 0x01, 0x07, 0x15, 0x01, 0x03, 0xA0, 0x01, 0x84, 0x80, 0x00, 0x01, 0x80, 0xC3, 0xFF, 0x7F, 0x04, 0x04, 0x25, 0x01, 0x00, 0x00, 0x6F, 0x05, 0x03, 0x25, 0x01, 0x00, 0x00, 0x00, 0x3A, 0x26, 0x05, 0x06, 0x41, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xB7, 0x33, 0x26, 0x3C, 0x06, 0x03, 0x3A, 0x25, 0x00, 0x01, 0x06, 0x0E, 0x3A, 0x26, 0x01, 0x06, 0x14, 0x01, 0x02, 0x10, 0x06, 0x04, 0x41, 0x01, 0x7F, 0x00, 0x01, 0x3F, 0x15, 0x09, 0x00, 0x00, 0x26, 0x06, 0x06, 0x0B, 0x9F, 0x33, 0x40, 0x04, 0x77, 0x25, 0x26, 0x00, 0x00, 0xB0, 0x01, 0x03, 0x75, 0xAA, 0xB7, 0x06, 0x02, 0x54, 0x29, 0x00, 0x00, 0x3A, 0x26, 0x06, 0x07, 0x31, 0x26, 0x06, 0x01, 0x1A, 0x04, 0x76, 0x41, 0x00, 0x00, 0x01, 0x01, 0x75, 0xA9, 0x01, 0x01, 0x10, 0x06, 0x02, 0x42, 0x29, 0xB7, 0x3D, 0x00, 0x04, 0xB0, 0x26, 0x01, 0x17, 0x01, 0x18, 0x6F, 0x05, 0x02, 0x47, 0x29, 0x01, 0x18, 0x11, 0x03, 0x00, 0x72, 0xAA, 0xA5, 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0xA5, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x26, 0x01, 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80, 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02, 0x01, 0x01, 0x82, 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02, 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01, 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01, 0x01, 0x01, 0x0C, 0xA6, 0x40, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, 0x07, 0x3E, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x3D, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3E, 0x2F, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09, 0x91, 0x09, 0x78, 0x26, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x3A, 0xA6, 0x02, 0x03, 0x09, 0x40, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0xA6, 0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0xA6, 0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0xA6, 0x02, 0x02, 0x09, 0x03, 0x02, 0xB7, 0x26, 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x25, 0xB7, 0x26, 0x01, 0x30, 0x01, 0x39, 0x6F, 0x06, 0x03, 0x25, 0x04, 0x74, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x47, 0x29, 0x76, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0xB7, 0x7A, 0x01, 0x0A, 0x08, 0x03, 0x00, 0xB7, 0x7A, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0xA5, 0x26, 0x02, 0x01, 0x02, 0x00, 0x6F, 0x05, 0x02, 0x47, 0x29, 0x00, 0x00, 0x33, 0xB0, 0x01, 0x02, 0x75, 0x0B, 0xA8, 0x00, 0x03, 0x26, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0xAA, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x53, 0x29, 0x26, 0x01, 0x00, 0x11, 0x06, 0x0B, 0x25, 0x26, 0x05, 0x04, 0x25, 0x01, 0x00, 0x00, 0xB7, 0x04, 0x6F, 0x02, 0x01, 0x26, 0x05, 0x02, 0x4F, 0x29, 0x40, 0x03, 0x01, 0x02, 0x02, 0x36, 0x02, 0x02, 0x3F, 0x03, 0x02, 0x26, 0x06, 0x03, 0xB7, 0x04, 0x68, 0x25, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00, 0x01, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x26, 0x05, 0x02, 0x4D, 0x29, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x19, 0x02, 0x00, 0x40, 0x03, 0x00, 0x26, 0x01, 0x83, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4E, 0x29, 0x01, 0x08, 0x0E, 0x3A, 0xB7, 0x33, 0x09, 0x04, 0x60, 0x00, 0x00, 0xA9, 0x92, 0x00, 0x00, 0xAA, 0xBF, 0x00, 0x00, 0xB0, 0x73, 0xAA, 0x00, 0x01, 0xAA, 0x26, 0x05, 0x02, 0x53, 0x29, 0xB7, 0x26, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x53, 0x29, 0x03, 0x00, 0x26, 0x06, 0x16, 0xB7, 0x02, 0x00, 0x26, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x53, 0x29, 0x01, 0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, 0x25, 0x02, 0x00, 0x00, 0x00, 0xAA, 0x26, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x08, 0xBF, 0x01, 0x00, 0x66, 0x36, 0x01, 0x00, 0x00, 0x26, 0x66, 0x36, 0x66, 0x3F, 0xA2, 0x01, 0x7F, 0x00, 0x00, 0xB0, 0x01, 0x0C, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB3, 0x04, 0x3E, 0x01, 0x12, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, 0x04, 0x33, 0x01, 0x13, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, 0x04, 0x28, 0x01, 0x14, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, 0x04, 0x1D, 0x01, 0x16, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB4, 0x04, 0x12, 0x01, 0x1E, 0x30, 0x11, 0x06, 0x05, 0x25, 0x72, 0xB2, 0x04, 0x07, 0x41, 0xAB, 0x01, 0x00, 0x01, 0x00, 0x25, 0x00, 0x01, 0xB7, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05, 0x14, 0x01, 0x01, 0x15, 0x2D, 0x02, 0x00, 0x01, 0x06, 0x14, 0x26, 0x01, 0x01, 0x15, 0x06, 0x02, 0x45, 0x29, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01, 0x1F, 0x15, 0x26, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x46, 0x29, 0x09, 0x00, 0x00, 0x26, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xB0, 0x00, 0x01, 0xAA, 0x26, 0x05, 0x05, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x03, 0x00, 0x9C, 0x26, 0x01, 0x83, 0xFF, 0x7E, 0x11, 0x06, 0x16, 0x25, 0x26, 0x06, 0x10, 0x9D, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, 0x00, 0x04, 0x6D, 0x04, 0x1B, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, 0x00, 0x26, 0x06, 0x0B, 0x9C, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, 0x01, 0x00, 0x40, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x01, 0xAA, 0x01, 0x01, 0x03, 0x00, 0x26, 0x06, 0x10, 0x9E, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, 0x01, 0x00, 0x40, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x01, 0xAA, 0x01, 0x01, 0x03, 0x00, 0x26, 0x06, 0x10, 0xB7, 0x26, 0x05, 0x05, 0x25, 0xBF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x81, 0x03, 0x00, 0x04, 0x6D, 0x25, 0x02, 0x00, 0x26, 0x05, 0x01, 0x00, 0x40, 0x66, 0x36, 0x01, 0x7F, 0x00, 0x00, 0xB7, 0x01, 0x08, 0x0E, 0x3A, 0xB7, 0x33, 0x09, 0x00, 0x00, 0xB7, 0x3A, 0xB7, 0x01, 0x08, 0x0E, 0x33, 0x09, 0x00, 0x00, 0x26, 0x05, 0x02, 0x4E, 0x29, 0x40, 0xB8, 0x00, 0x00, 0x32, 0x26, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x25, 0x1A, 0x04, 0x74, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0xC0, 0x25, 0x00, 0x00, 0x26, 0x06, 0x07, 0xC1, 0x26, 0x06, 0x01, 0x1A, 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x30, 0x31, 0x0B, 0x41, 0x00, 0x00, 0x01, 0x81, 0x70, 0x00, 0x00, 0x01, 0x82, 0x0D, 0x00, 0x00, 0x01, 0x82, 0x22, 0x00, 0x00, 0x01, 0x82, 0x05, 0x00, 0x00, 0x26, 0x01, 0x83, 0xFB, 0x50, 0x01, 0x83, 0xFB, 0x6F, 0x6F, 0x06, 0x04, 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x83, 0xB0, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x6F, 0x06, 0x04, 0x25, 0x01, 0x00, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x15, 0x01, 0x83, 0xFF, 0x7E, 0x0D, 0x00 }; static const uint16_t t0_caddr[] = { 0, 5, 10, 15, 20, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 135, 140, 145, 150, 155, 160, 165, 173, 178, 183, 188, 193, 198, 203, 208, 213, 234, 239, 244, 249, 264, 269, 275, 281, 286, 294, 302, 308, 313, 324, 960, 975, 979, 984, 989, 994, 999, 1004, 1118, 1123, 1135, 1140, 1145, 1150, 1154, 1159, 1164, 1169, 1174, 1184, 1189, 1194, 1206, 1221, 1226, 1240, 1262, 1273, 1376, 1423, 1456, 1547, 1553, 1616, 1623, 1651, 1679, 1784, 1826, 1839, 1851, 1865, 1880, 2100, 2114, 2131, 2140, 2207, 2263, 2267, 2271, 2276, 2324, 2350, 2426, 2470, 2481, 2566, 2604, 2642, 2652, 2662, 2671, 2684, 2688, 2692, 2696, 2700, 2704, 2708, 2712, 2724, 2732, 2737, 2742, 2747, 2752 }; #define T0_INTERPRETED 60 #define T0_ENTER(ip, rp, slot) do { \ const unsigned char *t0_newip; \ uint32_t t0_lnum; \ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ t0_lnum = t0_parse7E_unsigned(&t0_newip); \ (rp) += t0_lnum; \ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ (ip) = t0_newip; \ } while (0) #define T0_DEFENTRY(name, slot) \ void \ name(void *ctx) \ { \ t0_context *t0ctx = ctx; \ t0ctx->ip = &t0_codeblock[0]; \ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ } T0_DEFENTRY(br_x509_minimal_init_main, 144) #define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) void br_x509_minimal_run(void *t0ctx) { uint32_t *dp, *rp; const unsigned char *ip; #define T0_LOCAL(x) (*(rp - 2 - (x))) #define T0_POP() (*-- dp) #define T0_POPi() (*(int32_t *)(-- dp)) #define T0_PEEK(x) (*(dp - 1 - (x))) #define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) #define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) #define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) #define T0_RPOP() (*-- rp) #define T0_RPOPi() (*(int32_t *)(-- rp)) #define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) #define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) #define T0_ROLL(x) do { \ size_t t0len = (size_t)(x); \ uint32_t t0tmp = *(dp - 1 - t0len); \ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_SWAP() do { \ uint32_t t0tmp = *(dp - 2); \ *(dp - 2) = *(dp - 1); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_ROT() do { \ uint32_t t0tmp = *(dp - 3); \ *(dp - 3) = *(dp - 2); \ *(dp - 2) = *(dp - 1); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_NROT() do { \ uint32_t t0tmp = *(dp - 1); \ *(dp - 1) = *(dp - 2); \ *(dp - 2) = *(dp - 3); \ *(dp - 3) = t0tmp; \ } while (0) #define T0_PICK(x) do { \ uint32_t t0depth = (x); \ T0_PUSH(T0_PEEK(t0depth)); \ } while (0) #define T0_CO() do { \ goto t0_exit; \ } while (0) #define T0_RET() goto t0_next dp = ((t0_context *)t0ctx)->dp; rp = ((t0_context *)t0ctx)->rp; ip = ((t0_context *)t0ctx)->ip; goto t0_next; for (;;) { uint32_t t0x; t0_next: t0x = T0_NEXT(&ip); if (t0x < T0_INTERPRETED) { switch (t0x) { int32_t t0off; case 0: /* ret */ t0x = T0_RPOP(); rp -= (t0x >> 16); t0x &= 0xFFFF; if (t0x == 0) { ip = NULL; goto t0_exit; } ip = &t0_codeblock[t0x]; break; case 1: /* literal constant */ T0_PUSHi(t0_parse7E_signed(&ip)); break; case 2: /* read local */ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); break; case 3: /* write local */ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); break; case 4: /* jump */ t0off = t0_parse7E_signed(&ip); ip += t0off; break; case 5: /* jump if */ t0off = t0_parse7E_signed(&ip); if (T0_POP()) { ip += t0off; } break; case 6: /* jump if not */ t0off = t0_parse7E_signed(&ip); if (!T0_POP()) { ip += t0off; } break; case 7: { /* %25 */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSHi(a % b); } break; case 8: { /* * */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(a * b); } break; case 9: { /* + */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(a + b); } break; case 10: { /* - */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(a - b); } break; case 11: { /* -rot */ T0_NROT(); } break; case 12: { /* / */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSHi(a / b); } break; case 13: { /* < */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSH(-(uint32_t)(a < b)); } break; case 14: { /* << */ int c = (int)T0_POPi(); uint32_t x = T0_POP(); T0_PUSH(x << c); } break; case 15: { /* <= */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSH(-(uint32_t)(a <= b)); } break; case 16: { /* <> */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(-(uint32_t)(a != b)); } break; case 17: { /* = */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(-(uint32_t)(a == b)); } break; case 18: { /* > */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSH(-(uint32_t)(a > b)); } break; case 19: { /* >= */ int32_t b = T0_POPi(); int32_t a = T0_POPi(); T0_PUSH(-(uint32_t)(a >= b)); } break; case 20: { /* >> */ int c = (int)T0_POPi(); int32_t x = T0_POPi(); T0_PUSHi(x >> c); } break; case 21: { /* and */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(a & b); } break; case 22: { /* blobcopy */ size_t len = T0_POP(); unsigned char *src = (unsigned char *)CTX + T0_POP(); unsigned char *dst = (unsigned char *)CTX + T0_POP(); memcpy(dst, src, len); } break; case 23: { /* check-direct-trust */ size_t u; for (u = 0; u < CTX->trust_anchors_num; u ++) { const br_x509_trust_anchor *ta; unsigned char hashed_DN[64]; int kt; ta = &CTX->trust_anchors[u]; if (ta->flags & BR_X509_TA_CA) { continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { continue; } kt = CTX->pkey.key_type; if ((ta->pkey.key_type & 0x0F) != kt) { continue; } switch (kt) { case BR_KEYTYPE_RSA: if (!eqbigint(CTX->pkey.key.rsa.n, CTX->pkey.key.rsa.nlen, ta->pkey.key.rsa.n, ta->pkey.key.rsa.nlen) || !eqbigint(CTX->pkey.key.rsa.e, CTX->pkey.key.rsa.elen, ta->pkey.key.rsa.e, ta->pkey.key.rsa.elen)) { continue; } break; case BR_KEYTYPE_EC: if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen || memcmp(CTX->pkey.key.ec.q, ta->pkey.key.ec.q, ta->pkey.key.ec.qlen) != 0) { continue; } break; default: continue; } /* * Direct trust match! */ CTX->err = BR_ERR_X509_OK; T0_CO(); } } break; case 24: { /* check-trust-anchor-CA */ size_t u; for (u = 0; u < CTX->trust_anchors_num; u ++) { const br_x509_trust_anchor *ta; unsigned char hashed_DN[64]; ta = &CTX->trust_anchors[u]; if (!(ta->flags & BR_X509_TA_CA)) { continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { continue; } if (verify_signature(CTX, &ta->pkey) == 0) { CTX->err = BR_ERR_X509_OK; T0_CO(); } } } break; case 25: { /* check-validity-range */ uint32_t nbs = T0_POP(); uint32_t nbd = T0_POP(); uint32_t nas = T0_POP(); uint32_t nad = T0_POP(); int r; if (CTX->itime != 0) { r = CTX->itime(CTX->itime_ctx, nbd, nbs, nad, nas); if (r < -1 || r > 1) { CTX->err = BR_ERR_X509_TIME_UNKNOWN; T0_CO(); } } else { uint32_t vd = CTX->days; uint32_t vs = CTX->seconds; if (vd == 0 && vs == 0) { #if BR_USE_UNIX_TIME time_t x = time(NULL); vd = (uint32_t)(x / 86400) + 719528; vs = (uint32_t)(x % 86400); #elif BR_USE_WIN32_TIME FILETIME ft; uint64_t x; GetSystemTimeAsFileTime(&ft); x = ((uint64_t)ft.dwHighDateTime << 32) + (uint64_t)ft.dwLowDateTime; x = (x / 10000000); vd = (uint32_t)(x / 86400) + 584754; vs = (uint32_t)(x % 86400); #else CTX->err = BR_ERR_X509_TIME_UNKNOWN; T0_CO(); #endif } if (vd < nbd || (vd == nbd && vs < nbs)) { r = -1; } else if (vd > nad || (vd == nad && vs > nas)) { r = 1; } else { r = 0; } } T0_PUSHi(r); } break; case 26: { /* co */ T0_CO(); } break; case 27: { /* compute-dn-hash */ CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash); CTX->do_dn_hash = 0; } break; case 28: { /* compute-tbs-hash */ int id = T0_POPi(); size_t len; len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash); T0_PUSH(len); } break; case 29: { /* copy-ee-ec-pkey */ size_t qlen = T0_POP(); uint32_t curve = T0_POP(); memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); CTX->pkey.key_type = BR_KEYTYPE_EC; CTX->pkey.key.ec.curve = curve; CTX->pkey.key.ec.q = CTX->ee_pkey_data; CTX->pkey.key.ec.qlen = qlen; } break; case 30: { /* copy-ee-rsa-pkey */ size_t elen = T0_POP(); size_t nlen = T0_POP(); memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); CTX->pkey.key_type = BR_KEYTYPE_RSA; CTX->pkey.key.rsa.n = CTX->ee_pkey_data; CTX->pkey.key.rsa.nlen = nlen; CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen; CTX->pkey.key.rsa.elen = elen; } break; case 31: { /* copy-name-SAN */ unsigned tag = T0_POP(); unsigned ok = T0_POP(); size_t u, len; len = CTX->pad[0]; for (u = 0; u < CTX->num_name_elts; u ++) { br_name_element *ne; ne = &CTX->name_elts[u]; if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { if (ok && ne->len > len) { memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { ne->status = -1; } break; } } } break; case 32: { /* copy-name-element */ size_t len; int32_t off = T0_POPi(); int ok = T0_POPi(); if (off >= 0) { br_name_element *ne = &CTX->name_elts[off]; if (ok) { len = CTX->pad[0]; if (len < ne->len) { memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { ne->status = -1; } } else { ne->status = -1; } } } break; case 33: { /* data-get8 */ size_t addr = T0_POP(); T0_PUSH(t0_datablock[addr]); } break; case 34: { /* dn-hash-length */ T0_PUSH(DNHASH_LEN); } break; case 35: { /* do-ecdsa-vrfy */ size_t qlen = T0_POP(); int curve = T0_POP(); br_x509_pkey pk; pk.key_type = BR_KEYTYPE_EC; pk.key.ec.curve = curve; pk.key.ec.q = CTX->pkey_data; pk.key.ec.qlen = qlen; T0_PUSH(verify_signature(CTX, &pk)); } break; case 36: { /* do-rsa-vrfy */ size_t elen = T0_POP(); size_t nlen = T0_POP(); br_x509_pkey pk; pk.key_type = BR_KEYTYPE_RSA; pk.key.rsa.n = CTX->pkey_data; pk.key.rsa.nlen = nlen; pk.key.rsa.e = CTX->pkey_data + nlen; pk.key.rsa.elen = elen; T0_PUSH(verify_signature(CTX, &pk)); } break; case 37: { /* drop */ (void)T0_POP(); } break; case 38: { /* dup */ T0_PUSH(T0_PEEK(0)); } break; case 39: { /* eqOID */ const unsigned char *a2 = &t0_datablock[T0_POP()]; const unsigned char *a1 = &CTX->pad[0]; size_t len = a1[0]; int x; if (len == a2[0]) { x = -(memcmp(a1 + 1, a2 + 1, len) == 0); } else { x = 0; } T0_PUSH((uint32_t)x); } break; case 40: { /* eqblob */ size_t len = T0_POP(); const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); T0_PUSHi(-(memcmp(a1, a2, len) == 0)); } break; case 41: { /* fail */ CTX->err = T0_POPi(); T0_CO(); } break; case 42: { /* get16 */ uint32_t addr = T0_POP(); T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr)); } break; case 43: { /* get32 */ uint32_t addr = T0_POP(); T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr)); } break; case 44: { /* match-server-name */ size_t n1, n2; if (CTX->server_name == NULL) { T0_PUSH(0); T0_RET(); } n1 = strlen(CTX->server_name); n2 = CTX->pad[0]; if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { T0_PUSHi(-1); T0_RET(); } if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') { size_t u; u = 0; while (u < n1 && CTX->server_name[u] != '.') { u ++; } u ++; n1 -= u; if ((n2 - 2) == n1 && eqnocase(&CTX->pad[3], CTX->server_name + u, n1)) { T0_PUSHi(-1); T0_RET(); } } T0_PUSH(0); } break; case 45: { /* neg */ uint32_t a = T0_POP(); T0_PUSH(-a); } break; case 46: { /* offset-name-element */ unsigned san = T0_POP(); size_t u; for (u = 0; u < CTX->num_name_elts; u ++) { if (CTX->name_elts[u].status == 0) { const unsigned char *oid; size_t len, off; oid = CTX->name_elts[u].oid; if (san) { if (oid[0] != 0 || oid[1] != 0) { continue; } off = 2; } else { off = 0; } len = oid[off]; if (len != 0 && len == CTX->pad[0] && memcmp(oid + off + 1, CTX->pad + 1, len) == 0) { T0_PUSH(u); T0_RET(); } } } T0_PUSHi(-1); } break; case 47: { /* or */ uint32_t b = T0_POP(); uint32_t a = T0_POP(); T0_PUSH(a | b); } break; case 48: { /* over */ T0_PUSH(T0_PEEK(1)); } break; case 49: { /* read-blob-inner */ uint32_t len = T0_POP(); uint32_t addr = T0_POP(); size_t clen = CTX->hlen; if (clen > len) { clen = (size_t)len; } if (addr != 0) { memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); } if (CTX->do_mhash) { br_multihash_update(&CTX->mhash, CTX->hbuf, clen); } if (CTX->do_dn_hash) { CTX->dn_hash_impl->update( &CTX->dn_hash.vtable, CTX->hbuf, clen); } CTX->hbuf += clen; CTX->hlen -= clen; T0_PUSH(addr + clen); T0_PUSH(len - clen); } break; case 50: { /* read8-low */ if (CTX->hlen == 0) { T0_PUSHi(-1); } else { unsigned char x = *CTX->hbuf ++; if (CTX->do_mhash) { br_multihash_update(&CTX->mhash, &x, 1); } if (CTX->do_dn_hash) { CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1); } CTX->hlen --; T0_PUSH(x); } } break; case 51: { /* rot */ T0_ROT(); } break; case 52: { /* set16 */ uint32_t addr = T0_POP(); *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); } break; case 53: { /* set32 */ uint32_t addr = T0_POP(); *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); } break; case 54: { /* set8 */ uint32_t addr = T0_POP(); *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); } break; case 55: { /* start-dn-hash */ CTX->dn_hash_impl->init(&CTX->dn_hash.vtable); CTX->do_dn_hash = 1; } break; case 56: { /* start-tbs-hash */ br_multihash_init(&CTX->mhash); CTX->do_mhash = 1; } break; case 57: { /* stop-tbs-hash */ CTX->do_mhash = 0; } break; case 58: { /* swap */ T0_SWAP(); } break; case 59: { /* zero-server-name */ T0_PUSHi(-(CTX->server_name == NULL)); } break; } } else { T0_ENTER(ip, rp, t0x); } } t0_exit: ((t0_context *)t0ctx)->dp = dp; ((t0_context *)t0ctx)->rp = rp; ((t0_context *)t0ctx)->ip = ip; } /* * Verify the signature on the certificate with the provided public key. * This function checks the public key type with regards to the expected * type. Returned value is either 0 on success, or a non-zero error code. */ static int verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) { int kt; kt = ctx->cert_signer_key_type; if ((pk->key_type & 0x0F) != kt) { return BR_ERR_X509_WRONG_KEY_TYPE; } switch (kt) { unsigned char tmp[64]; case BR_KEYTYPE_RSA: if (ctx->irsa == 0) { return BR_ERR_X509_UNSUPPORTED; } if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len, &t0_datablock[ctx->cert_sig_hash_oid], ctx->cert_sig_hash_len, &pk->key.rsa, tmp)) { return BR_ERR_X509_BAD_SIGNATURE; } if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { return BR_ERR_X509_BAD_SIGNATURE; } return 0; case BR_KEYTYPE_EC: if (ctx->iecdsa == 0) { return BR_ERR_X509_UNSUPPORTED; } if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash, ctx->cert_sig_hash_len, &pk->key.ec, ctx->cert_sig, ctx->cert_sig_len)) { return BR_ERR_X509_BAD_SIGNATURE; } return 0; default: return BR_ERR_X509_UNSUPPORTED; } }