From d40d23b60cf1a42188a441b59226db35da234fea Mon Sep 17 00:00:00 2001 From: Thomas Pornin Date: Sun, 17 Apr 2022 15:02:36 -0400 Subject: [PATCH] Added generic API for date range validation (with callbacks). --- T0Comp.exe | Bin 72704 -> 73216 bytes inc/bearssl_x509.h | 83 ++++- src/x509/x509_minimal.c | 751 ++++++++++++++++++++------------------- src/x509/x509_minimal.t0 | 78 ++-- test/test_x509.c | 210 ++++++----- 5 files changed, 631 insertions(+), 491 deletions(-) diff --git a/T0Comp.exe b/T0Comp.exe index 67eba109800eaebba3b6d72a00e5390a7089078e..de2364d69e075555677f324e70665250ea3e07c8 100755 GIT binary patch delta 28000 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 D&Oj7a delta 27840 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 F{}*Y&;zR%d diff --git a/inc/bearssl_x509.h b/inc/bearssl_x509.h index 49d2fba..7668e1d 100644 --- a/inc/bearssl_x509.h +++ b/inc/bearssl_x509.h @@ -625,6 +625,52 @@ typedef struct { } br_name_element; +/** + * \brief Callback for validity date checks. + * + * The function receives as parameter an arbitrary user-provided context, + * and the notBefore and notAfter dates specified in an X.509 certificate, + * both expressed as a number of days and a number of seconds: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * Each date and time is understood in the UTC time zone. The "Unix + * Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and + * seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. + * + * This function must return -1 if the current date is strictly before + * the "notBefore" time, or +1 if the current date is strictly after the + * "notAfter" time. If neither condition holds, then the function returns + * 0, which means that the current date falls within the validity range of + * the certificate. If the function returns a value distinct from -1, 0 + * and +1, then this is interpreted as an unavailability of the current + * time, which normally ends the validation process with a + * `BR_ERR_X509_TIME_UNKNOWN` error. + * + * During path validation, this callback will be invoked for each + * considered X.509 certificate. Validation fails if any of the calls + * returns a non-zero value. + * + * The context value is an abritrary pointer set by the caller when + * configuring this callback. + * + * \param tctx context pointer. + * \param not_before_days notBefore date (days since Jan 1st, 0 AD). + * \param not_before_seconds notBefore time (seconds, at most 86400). + * \param not_after_days notAfter date (days since Jan 1st, 0 AD). + * \param not_after_seconds notAfter time (seconds, at most 86400). + * \return -1, 0 or +1. + */ +typedef int (*br_x509_time_check)(void *tctx, + uint32_t not_before_days, uint32_t not_before_seconds, + uint32_t not_after_days, uint32_t not_after_seconds); + /** * \brief The "minimal" X.509 engine structure. * @@ -647,8 +693,8 @@ typedef struct { uint32_t *rp; const unsigned char *ip; } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; + uint32_t dp_stack[31]; + uint32_t rp_stack[31]; int err; /* Server name to match with the SAN / CN of the EE certificate. */ @@ -723,6 +769,12 @@ typedef struct { br_name_element *name_elts; size_t num_name_elts; + /* + * Callback function (and context) to get the current date. + */ + void *itime_ctx; + br_x509_time_check itime; + /* * Public key cryptography implementations (signature verification). */ @@ -853,7 +905,10 @@ void br_x509_minimal_init_full(br_x509_minimal_context *ctx, * - Seconds are counted since midnight, from 0 to 86400 (a count of * 86400 is possible only if a leap second happened). * - * The validation date and time is understood in the UTC time zone. + * The validation date and time is understood in the UTC time zone. The + * "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 + * and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is + * days=584754, seconds=0. * * If the validation date and time are not explicitly set, but BearSSL * was compiled with support for the system clock on the underlying @@ -871,6 +926,28 @@ br_x509_minimal_set_time(br_x509_minimal_context *ctx, { ctx->days = days; ctx->seconds = seconds; + ctx->itime = 0; +} + +/** + * \brief Set the validity range callback function for the X.509 + * "minimal" engine. + * + * The provided function will be invoked to check whether the validation + * date is within the validity range for a given X.509 certificate; a + * call will be issued for each considered certificate. The provided + * context pointer (itime_ctx) will be passed as first parameter to the + * callback. + * + * \param tctx context for callback invocation. + * \param cb callback function. + */ +static inline void +br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx, + void *itime_ctx, br_x509_time_check itime) +{ + ctx->itime_ctx = itime_ctx; + ctx->itime = itime; } /** diff --git a/src/x509/x509_minimal.c b/src/x509/x509_minimal.c index 6103c08..04f149b 100644 --- a/src/x509/x509_minimal.c +++ b/src/x509/x509_minimal.c @@ -157,7 +157,7 @@ void br_x509_minimal_run(void *t0ctx); * -- 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 legnth compatible with + * 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 @@ -448,7 +448,7 @@ static const unsigned char t0_datablock[] = { 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, 0x24, 0x24, 0x00, 0x00, 0x01, + 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, @@ -486,227 +486,224 @@ static const unsigned char t0_codeblock[] = { 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, 0xC9, 0x71, - 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00, 0x00, - 0x01, 0x81, 0x02, 0x00, 0x00, 0x92, 0x05, 0x05, 0x34, 0x42, 0x01, 0x00, - 0x00, 0x34, 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, 0x04, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07, 0x02, 0x02, 0x02, 0x00, - 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D, 0x00, 0x02, 0x03, 0x00, - 0x03, 0x01, 0x25, 0x02, 0x01, 0x13, 0x3B, 0x02, 0x00, 0x0F, 0x15, 0x00, - 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x05, 0x02, 0x52, 0x28, 0x00, 0x00, - 0x06, 0x02, 0x53, 0x28, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x00, 0x11, - 0x05, 0x02, 0x56, 0x28, 0x74, 0x00, 0x00, 0x11, 0x05, 0x02, 0x56, 0x28, - 0x75, 0x00, 0x00, 0x06, 0x02, 0x4C, 0x28, 0x00, 0x00, 0x01, 0x82, 0x11, - 0x00, 0x00, 0x25, 0x20, 0x01, 0x08, 0x0E, 0x3B, 0x40, 0x20, 0x09, 0x00, - 0x09, 0x03, 0x00, 0x5B, 0x2B, 0xAF, 0x39, 0xAF, 0xB3, 0x25, 0x01, 0x20, - 0x11, 0x06, 0x11, 0x24, 0x74, 0xAD, 0xB3, 0x01, 0x02, 0x78, 0xB0, 0x01, - 0x02, 0x12, 0x06, 0x02, 0x57, 0x28, 0x79, 0xB3, 0x01, 0x02, 0x78, 0xAE, - 0xAF, 0xC2, 0x9C, 0x65, 0x61, 0x21, 0x16, 0xAF, 0xA7, 0x29, 0x69, 0x06, - 0x02, 0x4B, 0x28, 0xA7, 0x29, 0x71, 0x06, 0x02, 0x4B, 0x28, 0x79, 0x02, - 0x00, 0x06, 0x05, 0x9D, 0x03, 0x01, 0x04, 0x09, 0x9C, 0x61, 0x68, 0x21, - 0x27, 0x05, 0x02, 0x4A, 0x28, 0x68, 0x65, 0x21, 0x16, 0xAF, 0xAF, 0x9E, - 0x05, 0x02, 0x57, 0x28, 0xBC, 0x26, 0x06, 0x27, 0xC2, 0xA4, 0xAF, 0x63, - 0xAA, 0x03, 0x03, 0x63, 0x3B, 0x02, 0x03, 0x09, 0x3B, 0x02, 0x03, 0x0A, - 0xAA, 0x03, 0x04, 0x79, 0x64, 0x2A, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, - 0x12, 0x06, 0x02, 0x58, 0x28, 0x79, 0x5A, 0x03, 0x02, 0x04, 0x3A, 0x88, - 0x26, 0x06, 0x34, 0x9E, 0x05, 0x02, 0x57, 0x28, 0x6A, 0x26, 0x06, 0x04, - 0x01, 0x17, 0x04, 0x12, 0x6B, 0x26, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A, - 0x6C, 0x26, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x57, 0x28, 0x03, 0x05, - 0x79, 0xA4, 0x25, 0x03, 0x06, 0x25, 0x63, 0x34, 0x0D, 0x06, 0x02, 0x50, - 0x28, 0xA5, 0x59, 0x03, 0x02, 0x04, 0x02, 0x57, 0x28, 0x79, 0x02, 0x00, - 0x06, 0x21, 0x02, 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03, - 0x02, 0x04, 0x1D, 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, - 0x05, 0x02, 0x06, 0x1C, 0x04, 0x03, 0x57, 0x28, 0x24, 0x04, 0x24, 0x02, - 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03, 0x02, 0x04, 0x23, - 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x05, 0x02, 0x06, - 0x22, 0x04, 0x03, 0x57, 0x28, 0x24, 0x25, 0x06, 0x01, 0x28, 0x24, 0x01, - 0x00, 0x03, 0x07, 0xB4, 0x01, 0x21, 0x8F, 0x01, 0x22, 0x8F, 0x25, 0x01, - 0x23, 0x11, 0x06, 0x81, 0x26, 0x24, 0x74, 0xAD, 0xAF, 0x25, 0x06, 0x81, - 0x1A, 0x01, 0x00, 0x03, 0x08, 0xAF, 0x9E, 0x24, 0xB3, 0x25, 0x01, 0x01, - 0x11, 0x06, 0x04, 0xA6, 0x03, 0x08, 0xB3, 0x01, 0x04, 0x78, 0xAD, 0x70, - 0x26, 0x06, 0x0F, 0x02, 0x00, 0x06, 0x03, 0xC3, 0x04, 0x05, 0x99, 0x01, - 0x7F, 0x03, 0x07, 0x04, 0x80, 0x6C, 0x91, 0x26, 0x06, 0x06, 0x02, 0x00, - 0x9B, 0x04, 0x80, 0x62, 0xC5, 0x26, 0x06, 0x11, 0x02, 0x00, 0x06, 0x09, - 0x01, 0x00, 0x03, 0x01, 0x98, 0x03, 0x01, 0x04, 0x01, 0xC3, 0x04, 0x80, - 0x4D, 0x73, 0x26, 0x06, 0x0A, 0x02, 0x08, 0x06, 0x03, 0x9A, 0x04, 0x01, - 0xC3, 0x04, 0x3F, 0x6F, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x38, 0xC8, 0x26, - 0x06, 0x03, 0xC3, 0x04, 0x31, 0x90, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x2A, - 0xC6, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x23, 0x7A, 0x26, 0x06, 0x03, 0xC3, - 0x04, 0x1C, 0x85, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x15, 0x6E, 0x26, 0x06, - 0x03, 0xC3, 0x04, 0x0E, 0xC7, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x07, 0x02, - 0x08, 0x06, 0x02, 0x49, 0x28, 0xC3, 0x79, 0x79, 0x04, 0xFE, 0x62, 0x79, - 0x79, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x56, 0x28, 0x24, 0x79, - 0x3A, 0x02, 0x00, 0x06, 0x08, 0x02, 0x01, 0x3C, 0x2F, 0x05, 0x02, 0x45, - 0x28, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00, 0x02, 0x07, 0x2F, 0x05, - 0x02, 0x51, 0x28, 0xB3, 0x76, 0xAD, 0x9E, 0x06, 0x80, 0x77, 0xBD, 0x26, - 0x06, 0x07, 0x01, 0x02, 0x5A, 0x8A, 0x04, 0x80, 0x5E, 0xBE, 0x26, 0x06, - 0x07, 0x01, 0x03, 0x5A, 0x8B, 0x04, 0x80, 0x53, 0xBF, 0x26, 0x06, 0x07, - 0x01, 0x04, 0x5A, 0x8C, 0x04, 0x80, 0x48, 0xC0, 0x26, 0x06, 0x06, 0x01, - 0x05, 0x5A, 0x8D, 0x04, 0x3E, 0xC1, 0x26, 0x06, 0x06, 0x01, 0x06, 0x5A, - 0x8E, 0x04, 0x34, 0x7F, 0x26, 0x06, 0x06, 0x01, 0x02, 0x59, 0x8A, 0x04, - 0x2A, 0x80, 0x26, 0x06, 0x06, 0x01, 0x03, 0x59, 0x8B, 0x04, 0x20, 0x81, - 0x26, 0x06, 0x06, 0x01, 0x04, 0x59, 0x8C, 0x04, 0x16, 0x82, 0x26, 0x06, - 0x06, 0x01, 0x05, 0x59, 0x8D, 0x04, 0x0C, 0x83, 0x26, 0x06, 0x06, 0x01, - 0x06, 0x59, 0x8E, 0x04, 0x02, 0x57, 0x28, 0x5E, 0x35, 0x60, 0x37, 0x1B, - 0x25, 0x05, 0x02, 0x57, 0x28, 0x5D, 0x37, 0x04, 0x02, 0x57, 0x28, 0xC2, - 0xA4, 0x25, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x50, - 0x28, 0x25, 0x5F, 0x35, 0x5C, 0xA5, 0x79, 0x79, 0x01, 0x00, 0x5B, 0x36, - 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x25, 0x01, 0x00, 0x01, 0x09, 0x72, - 0x05, 0x02, 0x48, 0x28, 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, 0x7E, - 0x01, 0x01, 0x11, 0x3B, 0x01, 0x83, 0xFD, 0x7F, 0x11, 0x15, 0x06, 0x03, - 0x3B, 0x24, 0x00, 0x3B, 0x25, 0x03, 0x00, 0x25, 0xCA, 0x05, 0x04, 0x42, - 0x01, 0x00, 0x00, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x96, 0x04, - 0x80, 0x49, 0x25, 0x01, 0x90, 0x00, 0x0D, 0x06, 0x0F, 0x01, 0x06, 0x14, - 0x01, 0x81, 0x40, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x00, 0x97, 0x04, 0x33, - 0x25, 0x01, 0x83, 0xFF, 0x7F, 0x0D, 0x06, 0x14, 0x01, 0x0C, 0x14, 0x01, - 0x81, 0x60, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00, 0x01, - 0x00, 0x97, 0x04, 0x17, 0x01, 0x12, 0x14, 0x01, 0x81, 0x70, 0x2F, 0x96, - 0x02, 0x00, 0x01, 0x0C, 0x97, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00, - 0x01, 0x00, 0x97, 0x00, 0x00, 0x01, 0x82, 0x15, 0x00, 0x00, 0x25, 0x01, - 0x83, 0xB0, 0x00, 0x01, 0x83, 0xB7, 0x7F, 0x72, 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, 0x42, 0xAD, 0xC2, 0xB4, 0x00, 0x00, 0x01, - 0x82, 0x09, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x25, 0x01, 0x83, - 0xB8, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x00, 0x00, 0x01, 0x30, 0x62, - 0x37, 0x01, 0x7F, 0x7C, 0x19, 0x01, 0x00, 0x7C, 0x19, 0x04, 0x7A, 0x00, - 0x01, 0x81, 0x38, 0x00, 0x01, 0x7E, 0x0D, 0x06, 0x02, 0x4F, 0x28, 0x25, - 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x30, 0x25, 0x3F, 0x3B, 0x01, - 0x82, 0x00, 0x13, 0x2F, 0x06, 0x04, 0x42, 0x01, 0x00, 0x00, 0x30, 0x67, - 0x09, 0x37, 0x40, 0x00, 0x00, 0x14, 0x01, 0x3F, 0x15, 0x01, 0x81, 0x00, - 0x2F, 0x96, 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, 0xAF, 0x25, 0x06, 0x80, - 0x59, 0xB3, 0x01, 0x20, 0x30, 0x11, 0x06, 0x17, 0x24, 0x74, 0xAD, 0x9E, - 0x24, 0x01, 0x7F, 0x2E, 0x03, 0x01, 0xB3, 0x01, 0x20, 0x77, 0xAD, 0xB2, - 0x02, 0x01, 0x1F, 0x79, 0x79, 0x04, 0x38, 0x01, 0x21, 0x30, 0x11, 0x06, - 0x08, 0x24, 0x75, 0xB6, 0x01, 0x01, 0x1E, 0x04, 0x2A, 0x01, 0x22, 0x30, - 0x11, 0x06, 0x11, 0x24, 0x75, 0xB6, 0x25, 0x06, 0x06, 0x2C, 0x02, 0x00, - 0x2F, 0x03, 0x00, 0x01, 0x02, 0x1E, 0x04, 0x13, 0x01, 0x26, 0x30, 0x11, - 0x06, 0x08, 0x24, 0x75, 0xB6, 0x01, 0x06, 0x1E, 0x04, 0x05, 0x42, 0xAE, - 0x01, 0x00, 0x24, 0x04, 0xFF, 0x23, 0x79, 0x02, 0x00, 0x00, 0x00, 0xAF, - 0xB4, 0x25, 0x01, 0x01, 0x11, 0x06, 0x08, 0xA6, 0x05, 0x02, 0x51, 0x28, - 0xB4, 0x04, 0x02, 0x51, 0x28, 0x25, 0x01, 0x02, 0x11, 0x06, 0x0C, 0x24, - 0x75, 0xB0, 0x66, 0x2B, 0x41, 0x0D, 0x06, 0x02, 0x51, 0x28, 0xB4, 0x01, - 0x7F, 0x10, 0x06, 0x02, 0x56, 0x28, 0x24, 0x79, 0x00, 0x00, 0xAF, 0x25, - 0x06, 0x1A, 0xAF, 0x9E, 0x24, 0x25, 0x06, 0x11, 0xAF, 0x25, 0x06, 0x0C, - 0xAF, 0x9E, 0x24, 0x89, 0x26, 0x05, 0x02, 0x49, 0x28, 0xC2, 0x04, 0x71, - 0x79, 0x79, 0x04, 0x63, 0x79, 0x00, 0x02, 0x03, 0x00, 0xB3, 0x01, 0x03, - 0x78, 0xAD, 0xBA, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02, - 0x56, 0x28, 0x25, 0x01, 0x00, 0x30, 0x11, 0x06, 0x05, 0x24, 0x4D, 0x28, - 0x04, 0x15, 0x01, 0x01, 0x30, 0x11, 0x06, 0x0A, 0x24, 0xBA, 0x02, 0x01, - 0x14, 0x02, 0x01, 0x0E, 0x04, 0x05, 0x24, 0xBA, 0x01, 0x00, 0x24, 0x02, - 0x00, 0x06, 0x19, 0x01, 0x00, 0x30, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01, - 0x10, 0x2F, 0x3B, 0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2F, - 0x62, 0x37, 0x04, 0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x4D, 0x28, 0xC2, - 0x00, 0x00, 0x38, 0xAF, 0xC2, 0x1A, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, - 0x38, 0xAF, 0x25, 0x06, 0x30, 0xB3, 0x01, 0x11, 0x77, 0xAD, 0x25, 0x05, - 0x02, 0x44, 0x28, 0x25, 0x06, 0x20, 0xAF, 0x9E, 0x24, 0x87, 0x26, 0x03, - 0x01, 0x01, 0x00, 0x2E, 0x03, 0x02, 0xB2, 0x25, 0x02, 0x01, 0x15, 0x06, - 0x07, 0x2C, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x02, 0x1F, 0x79, - 0x04, 0x5D, 0x79, 0x04, 0x4D, 0x79, 0x1A, 0x02, 0x00, 0x00, 0x00, 0xB3, - 0x01, 0x06, 0x78, 0xB1, 0x00, 0x00, 0xB8, 0x86, 0x06, 0x0E, 0x3B, 0x25, - 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00, 0xB8, 0x6D, 0x04, 0x08, - 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB9, 0x86, - 0x06, 0x0E, 0x3B, 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00, - 0xB9, 0x6D, 0x04, 0x08, 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00, - 0x00, 0x00, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x00, 0x04, - 0x80, 0x55, 0x25, 0x01, 0x81, 0x40, 0x0D, 0x06, 0x07, 0x24, 0x01, 0x00, - 0x00, 0x04, 0x80, 0x47, 0x25, 0x01, 0x81, 0x60, 0x0D, 0x06, 0x0E, 0x01, - 0x1F, 0x15, 0x01, 0x01, 0xA3, 0x01, 0x81, 0x00, 0x01, 0x8F, 0x7F, 0x04, - 0x32, 0x25, 0x01, 0x81, 0x70, 0x0D, 0x06, 0x0F, 0x01, 0x0F, 0x15, 0x01, - 0x02, 0xA3, 0x01, 0x90, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x04, 0x1C, 0x25, - 0x01, 0x81, 0x78, 0x0D, 0x06, 0x11, 0x01, 0x07, 0x15, 0x01, 0x03, 0xA3, - 0x01, 0x84, 0x80, 0x00, 0x01, 0x80, 0xC3, 0xFF, 0x7F, 0x04, 0x04, 0x24, - 0x01, 0x00, 0x00, 0x72, 0x05, 0x03, 0x24, 0x01, 0x00, 0x00, 0x00, 0x3B, - 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xBA, 0x34, 0x25, - 0x3D, 0x06, 0x03, 0x3B, 0x24, 0x00, 0x01, 0x06, 0x0E, 0x3B, 0x25, 0x01, - 0x06, 0x14, 0x01, 0x02, 0x10, 0x06, 0x04, 0x42, 0x01, 0x7F, 0x00, 0x01, - 0x3F, 0x15, 0x09, 0x00, 0x00, 0x25, 0x06, 0x06, 0x0B, 0xA2, 0x34, 0x41, - 0x04, 0x77, 0x24, 0x25, 0x00, 0x00, 0xB3, 0x01, 0x03, 0x78, 0xAD, 0xBA, - 0x06, 0x02, 0x55, 0x28, 0x00, 0x00, 0x3B, 0x25, 0x06, 0x07, 0x31, 0x25, - 0x06, 0x01, 0x19, 0x04, 0x76, 0x42, 0x00, 0x00, 0x01, 0x01, 0x78, 0xAC, - 0x01, 0x01, 0x10, 0x06, 0x02, 0x43, 0x28, 0xBA, 0x3E, 0x00, 0x04, 0xB3, - 0x25, 0x01, 0x17, 0x01, 0x18, 0x72, 0x05, 0x02, 0x48, 0x28, 0x01, 0x18, - 0x11, 0x03, 0x00, 0x75, 0xAD, 0xA8, 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, - 0x64, 0x08, 0x03, 0x01, 0xA8, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x25, 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, 0xA9, 0x41, 0x01, - 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, 0x07, 0x3F, 0x02, 0x01, 0x01, 0x80, - 0x64, 0x07, 0x3E, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3F, 0x2F, 0x15, - 0x06, 0x03, 0x01, 0x18, 0x09, 0x94, 0x09, 0x7B, 0x25, 0x01, 0x05, 0x14, - 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x3B, 0xA9, - 0x02, 0x03, 0x09, 0x41, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0xA9, 0x01, - 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0xA9, 0x01, 0x3C, - 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0xA9, 0x02, - 0x02, 0x09, 0x03, 0x02, 0xBA, 0x25, 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x24, - 0xBA, 0x25, 0x01, 0x30, 0x01, 0x39, 0x72, 0x06, 0x03, 0x24, 0x04, 0x74, - 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x48, 0x28, 0x79, 0x02, 0x03, 0x02, - 0x02, 0x00, 0x01, 0xBA, 0x7D, 0x01, 0x0A, 0x08, 0x03, 0x00, 0xBA, 0x7D, - 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0xA8, 0x25, 0x02, - 0x01, 0x02, 0x00, 0x72, 0x05, 0x02, 0x48, 0x28, 0x00, 0x00, 0x34, 0xB3, - 0x01, 0x02, 0x78, 0x0B, 0xAB, 0x00, 0x03, 0x25, 0x03, 0x00, 0x03, 0x01, - 0x03, 0x02, 0xAD, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x54, - 0x28, 0x25, 0x01, 0x00, 0x11, 0x06, 0x0B, 0x24, 0x25, 0x05, 0x04, 0x24, - 0x01, 0x00, 0x00, 0xBA, 0x04, 0x6F, 0x02, 0x01, 0x25, 0x05, 0x02, 0x50, - 0x28, 0x41, 0x03, 0x01, 0x02, 0x02, 0x37, 0x02, 0x02, 0x40, 0x03, 0x02, - 0x25, 0x06, 0x03, 0xBA, 0x04, 0x68, 0x24, 0x02, 0x00, 0x02, 0x01, 0x0A, - 0x00, 0x01, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, - 0x81, 0x00, 0x0A, 0x25, 0x05, 0x02, 0x4E, 0x28, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x19, 0x02, 0x00, 0x41, 0x03, 0x00, - 0x25, 0x01, 0x83, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4F, 0x28, 0x01, - 0x08, 0x0E, 0x3B, 0xBA, 0x34, 0x09, 0x04, 0x60, 0x00, 0x00, 0xAC, 0x95, - 0x00, 0x00, 0xAD, 0xC2, 0x00, 0x00, 0xB3, 0x76, 0xAD, 0x00, 0x01, 0xAD, - 0x25, 0x05, 0x02, 0x54, 0x28, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06, - 0x02, 0x54, 0x28, 0x03, 0x00, 0x25, 0x06, 0x16, 0xBA, 0x02, 0x00, 0x25, - 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x54, 0x28, 0x01, 0x08, - 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, 0x24, 0x02, 0x00, 0x00, 0x00, 0xAD, - 0x25, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x08, 0xC2, 0x01, 0x00, 0x67, 0x37, - 0x01, 0x00, 0x00, 0x25, 0x67, 0x37, 0x67, 0x40, 0xA5, 0x01, 0x7F, 0x00, - 0x00, 0xB3, 0x01, 0x0C, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB6, 0x04, - 0x3E, 0x01, 0x12, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x33, - 0x01, 0x13, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x28, 0x01, - 0x14, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x1D, 0x01, 0x16, - 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x12, 0x01, 0x1E, 0x30, - 0x11, 0x06, 0x05, 0x24, 0x75, 0xB5, 0x04, 0x07, 0x42, 0xAE, 0x01, 0x00, - 0x01, 0x00, 0x24, 0x00, 0x01, 0xBA, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05, - 0x14, 0x01, 0x01, 0x15, 0x2D, 0x02, 0x00, 0x01, 0x06, 0x14, 0x25, 0x01, - 0x01, 0x15, 0x06, 0x02, 0x46, 0x28, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01, - 0x1F, 0x15, 0x25, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x47, 0x28, 0x09, 0x00, - 0x00, 0x25, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xB3, 0x00, 0x01, - 0xAD, 0x25, 0x05, 0x05, 0x67, 0x37, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x03, - 0x00, 0x9F, 0x25, 0x01, 0x83, 0xFF, 0x7E, 0x11, 0x06, 0x16, 0x24, 0x25, - 0x06, 0x10, 0xA0, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x84, 0x03, 0x00, 0x04, 0x6D, 0x04, 0x1B, 0x25, 0x05, 0x05, 0x24, - 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x25, 0x06, 0x0B, - 0x9F, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x6D, 0x24, - 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01, 0x7F, 0x00, - 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xA1, 0x25, 0x05, - 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x04, - 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01, - 0x7F, 0x00, 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xBA, - 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, - 0x00, 0x04, 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, - 0x37, 0x01, 0x7F, 0x00, 0x00, 0xBA, 0x01, 0x08, 0x0E, 0x3B, 0xBA, 0x34, - 0x09, 0x00, 0x00, 0xBA, 0x3B, 0xBA, 0x01, 0x08, 0x0E, 0x34, 0x09, 0x00, - 0x00, 0x25, 0x05, 0x02, 0x4F, 0x28, 0x41, 0xBB, 0x00, 0x00, 0x32, 0x25, - 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x24, 0x19, 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, 0xC3, - 0x24, 0x00, 0x00, 0x25, 0x06, 0x07, 0xC4, 0x25, 0x06, 0x01, 0x19, 0x04, - 0x76, 0x00, 0x00, 0x01, 0x00, 0x30, 0x31, 0x0B, 0x42, 0x00, 0x00, 0x01, - 0x81, 0x70, 0x00, 0x00, 0x01, 0x82, 0x0D, 0x00, 0x00, 0x01, 0x82, 0x22, - 0x00, 0x00, 0x01, 0x82, 0x05, 0x00, 0x00, 0x01, 0x03, 0x33, 0x01, 0x03, - 0x33, 0x00, 0x00, 0x25, 0x01, 0x83, 0xFB, 0x50, 0x01, 0x83, 0xFB, 0x6F, - 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x83, 0xB0, 0x00, - 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x01, - 0x83, 0xFF, 0x7F, 0x15, 0x01, 0x83, 0xFF, 0x7E, 0x0D, 0x00 + 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[] = { @@ -755,106 +752,103 @@ static const uint16_t t0_caddr[] = { 188, 193, 198, - 202, - 207, - 212, - 217, - 238, - 243, - 248, - 253, - 282, - 297, + 203, + 208, + 213, + 234, + 239, + 244, + 249, + 264, + 269, + 275, + 281, + 286, + 294, 302, 308, - 314, - 319, - 327, - 335, - 341, - 346, - 357, - 992, - 1007, - 1011, - 1016, - 1021, - 1026, - 1031, - 1036, + 313, + 324, + 960, + 975, + 979, + 984, + 989, + 994, + 999, + 1004, + 1118, + 1123, + 1135, + 1140, + 1145, 1150, - 1155, - 1167, - 1172, - 1177, - 1182, - 1186, - 1191, - 1196, - 1201, + 1154, + 1159, + 1164, + 1169, + 1174, + 1184, + 1189, + 1194, 1206, - 1216, 1221, 1226, - 1238, - 1253, - 1258, - 1272, - 1294, - 1305, - 1408, - 1455, - 1488, - 1579, - 1585, - 1648, - 1655, - 1683, - 1711, - 1816, - 1858, - 1871, - 1883, - 1897, - 1912, - 2132, - 2146, - 2163, - 2172, - 2239, - 2295, - 2299, - 2303, - 2308, - 2356, - 2382, - 2458, - 2502, - 2513, - 2598, - 2636, - 2674, + 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, - 2694, - 2703, - 2716, - 2720, + 2688, + 2692, + 2696, + 2700, + 2704, + 2708, + 2712, 2724, - 2728, 2732, - 2736, - 2740, - 2744, - 2756, - 2764, - 2769, - 2774, - 2779, - 2784, - 2792 + 2737, + 2742, + 2747, + 2752 }; -#define T0_INTERPRETED 61 +#define T0_INTERPRETED 60 #define T0_ENTER(ip, rp, slot) do { \ const unsigned char *t0_newip; \ @@ -875,7 +869,7 @@ name(void *ctx) \ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ } -T0_DEFENTRY(br_x509_minimal_init_main, 147) +T0_DEFENTRY(br_x509_minimal_init_main, 144) #define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) @@ -1205,11 +1199,61 @@ br_x509_minimal_run(void *t0ctx) } 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 26: { + case 27: { /* compute-dn-hash */ CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash); @@ -1217,7 +1261,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 27: { + case 28: { /* compute-tbs-hash */ int id = T0_POPi(); @@ -1227,7 +1271,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 28: { + case 29: { /* copy-ee-ec-pkey */ size_t qlen = T0_POP(); @@ -1240,7 +1284,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 29: { + case 30: { /* copy-ee-rsa-pkey */ size_t elen = T0_POP(); @@ -1254,7 +1298,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 30: { + case 31: { /* copy-name-SAN */ unsigned tag = T0_POP(); @@ -1280,7 +1324,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 31: { + case 32: { /* copy-name-element */ size_t len; @@ -1306,7 +1350,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 32: { + case 33: { /* data-get8 */ size_t addr = T0_POP(); @@ -1314,14 +1358,14 @@ br_x509_minimal_run(void *t0ctx) } break; - case 33: { + case 34: { /* dn-hash-length */ T0_PUSH(DNHASH_LEN); } break; - case 34: { + case 35: { /* do-ecdsa-vrfy */ size_t qlen = T0_POP(); @@ -1336,7 +1380,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 35: { + case 36: { /* do-rsa-vrfy */ size_t elen = T0_POP(); @@ -1352,17 +1396,17 @@ br_x509_minimal_run(void *t0ctx) } break; - case 36: { + case 37: { /* drop */ (void)T0_POP(); } break; - case 37: { + case 38: { /* dup */ T0_PUSH(T0_PEEK(0)); } break; - case 38: { + case 39: { /* eqOID */ const unsigned char *a2 = &t0_datablock[T0_POP()]; @@ -1378,7 +1422,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 39: { + case 40: { /* eqblob */ size_t len = T0_POP(); @@ -1388,42 +1432,12 @@ br_x509_minimal_run(void *t0ctx) } break; - case 40: { + case 41: { /* fail */ CTX->err = T0_POPi(); T0_CO(); - } - break; - case 41: { - /* get-system-date */ - - if (CTX->days == 0 && CTX->seconds == 0) { -#if BR_USE_UNIX_TIME - time_t x = time(NULL); - - T0_PUSH((uint32_t)(x / 86400) + 719528); - T0_PUSH((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); - T0_PUSH((uint32_t)(x / 86400) + 584754); - T0_PUSH((uint32_t)(x % 86400)); -#else - CTX->err = BR_ERR_X509_TIME_UNKNOWN; - T0_CO(); -#endif - } else { - T0_PUSH(CTX->days); - T0_PUSH(CTX->seconds); - } - } break; case 42: { @@ -1579,16 +1593,11 @@ br_x509_minimal_run(void *t0ctx) } break; case 51: { - /* roll */ - T0_ROLL(T0_POP()); - } - break; - case 52: { /* rot */ T0_ROT(); } break; - case 53: { + case 52: { /* set16 */ uint32_t addr = T0_POP(); @@ -1596,7 +1605,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 54: { + case 53: { /* set32 */ uint32_t addr = T0_POP(); @@ -1604,7 +1613,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 55: { + case 54: { /* set8 */ uint32_t addr = T0_POP(); @@ -1612,7 +1621,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 56: { + case 55: { /* start-dn-hash */ CTX->dn_hash_impl->init(&CTX->dn_hash.vtable); @@ -1620,7 +1629,7 @@ br_x509_minimal_run(void *t0ctx) } break; - case 57: { + case 56: { /* start-tbs-hash */ br_multihash_init(&CTX->mhash); @@ -1628,19 +1637,19 @@ br_x509_minimal_run(void *t0ctx) } break; - case 58: { + case 57: { /* stop-tbs-hash */ CTX->do_mhash = 0; } break; - case 59: { + case 58: { /* swap */ T0_SWAP(); } break; - case 60: { + case 59: { /* zero-server-name */ T0_PUSHi(-(CTX->server_name == NULL)); diff --git a/src/x509/x509_minimal.t0 b/src/x509/x509_minimal.t0 index 50995dc..80a3701 100644 --- a/src/x509/x509_minimal.t0 +++ b/src/x509/x509_minimal.t0 @@ -698,42 +698,60 @@ cc: copy-name-SAN ( bool tag -- ) { \ Return the CN match flag. eename-matches ; -\ Get the validation date and time from the context or system. -cc: get-system-date ( -- days seconds ) { - if (CTX->days == 0 && CTX->seconds == 0) { +\ Check the provided validity range against the current (or configured) +\ date and time ("na" = notAfter, "nb = notBefore). Returned value: +\ -1 current date/time is before the notBefore date +\ 0 current date/time is within the allowed range +\ +1 current date/time is after the notAfter range +\ If the current date/time is not available, then this function triggers a +\ failure and does not return. +cc: check-validity-range ( na-days na-seconds nb-days nb-seconds -- int ) { + 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); + time_t x = time(NULL); - T0_PUSH((uint32_t)(x / 86400) + 719528); - T0_PUSH((uint32_t)(x % 86400)); + 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); - T0_PUSH((uint32_t)(x / 86400) + 584754); - T0_PUSH((uint32_t)(x % 86400)); + 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(); + CTX->err = BR_ERR_X509_TIME_UNKNOWN; + T0_CO(); #endif - } else { - T0_PUSH(CTX->days); - T0_PUSH(CTX->seconds); + } + 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); } -\ Compare two dates (days+seconds) together. -: before ( days1 seconds1 days2 seconds2 -- bool ) - { d1 s1 d2 s2 } - d1 d2 = if s1 s2 < else d1 d2 < then ; - -: after ( days1 seconds1 days2 seconds2 -- bool ) - swap2 before ; - \ Swap the top two elements with the two elements immediately below. : swap2 ( a b c d -- c d a b ) 3 roll 3 roll ; @@ -1189,8 +1207,8 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11 \ Validity dates. read-sequence-open - read-date get-system-date after if ERR_X509_EXPIRED fail then - read-date get-system-date before if ERR_X509_EXPIRED fail then + read-date { nbd nbs } read-date nbd nbs check-validity-range + if ERR_X509_EXPIRED fail then close-elt \ Subject name. diff --git a/test/test_x509.c b/test/test_x509.c index 2c61cf5..c007068 100644 --- a/test/test_x509.c +++ b/test/test_x509.c @@ -1438,6 +1438,21 @@ eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2) static size_t max_dp_usage; static size_t max_rp_usage; +static int +check_time(void *ctx, uint32_t nbd, uint32_t nbs, uint32_t nad, uint32_t nas) +{ + test_case *tc; + + tc = ctx; + if (tc->days < nbd || (tc->days == nbd && tc->seconds < nbs)) { + return -1; + } + if (tc->days > nad || (tc->days == nad && tc->seconds > nas)) { + return 1; + } + return 0; +} + static void run_test_case(test_case *tc) { @@ -1452,6 +1467,7 @@ run_test_case(test_case *tc) const br_x509_pkey *ee_pkey; unsigned usages; unsigned status; + int j; printf("%s: ", tc->name); fflush(stdout); @@ -1520,110 +1536,130 @@ run_test_case(test_case *tc) } /* - * Initialise the engine. + * We do the test twice, to exercise distinct API functions. */ - br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors); - for (u = 0; hash_impls[u].id; u ++) { - int id; + for (j = 0; j < 2; j ++) { + /* + * Initialise the engine. + */ + br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors); + for (u = 0; hash_impls[u].id; u ++) { + int id; + + id = hash_impls[u].id; + if ((tc->hashes & ((unsigned)1 << id)) != 0) { + br_x509_minimal_set_hash(&ctx, + id, hash_impls[u].impl); + } + } + br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); + br_x509_minimal_set_ecdsa(&ctx, + br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); - id = hash_impls[u].id; - if ((tc->hashes & ((unsigned)1 << id)) != 0) { - br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl); + /* + * Set the validation date. + */ + if (j == 0) { + br_x509_minimal_set_time(&ctx, tc->days, tc->seconds); + } else { + br_x509_minimal_set_time_callback(&ctx, + tc, &check_time); } - } - br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); - br_x509_minimal_set_ecdsa(&ctx, - br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); - /* - * Set the validation date. - */ - br_x509_minimal_set_time(&ctx, tc->days, tc->seconds); + /* + * Put "canaries" to detect actual stack usage. + */ + for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); + u ++) + { + ctx.dp_stack[u] = 0xA7C083FE; + } + for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); + u ++) + { + ctx.rp_stack[u] = 0xA7C083FE; + } - /* - * Put "canaries" to detect actual stack usage. - */ - for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) { - ctx.dp_stack[u] = 0xA7C083FE; - } - for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) { - ctx.rp_stack[u] = 0xA7C083FE; - } + /* + * Run the engine. We inject certificates by chunks of 100 + * bytes in order to exercise the coroutine API. + */ + ctx.vtable->start_chain(&ctx.vtable, tc->servername); + for (u = 0; u < num_certs; u ++) { + size_t v; - /* - * Run the engine. We inject certificates by chunks of 100 bytes - * in order to exercise the coroutine API. - */ - ctx.vtable->start_chain(&ctx.vtable, tc->servername); - for (u = 0; u < num_certs; u ++) { - size_t v; + ctx.vtable->start_cert(&ctx.vtable, certs[u].len); + v = 0; + while (v < certs[u].len) { + size_t w; - ctx.vtable->start_cert(&ctx.vtable, certs[u].len); - v = 0; - while (v < certs[u].len) { - size_t w; + w = certs[u].len - v; + if (w > 100) { + w = 100; + } + ctx.vtable->append(&ctx.vtable, + certs[u].data + v, w); + v += w; + } + ctx.vtable->end_cert(&ctx.vtable); + } + status = ctx.vtable->end_chain(&ctx.vtable); + ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages); - w = certs[u].len - v; - if (w > 100) { - w = 100; + /* + * Check key type and usage. + */ + if (ee_pkey != NULL) { + unsigned ktu; + + ktu = ee_pkey->key_type | usages; + if (tc->key_type_usage != (ktu & tc->key_type_usage)) { + fprintf(stderr, "wrong key type + usage" + " (expected 0x%02X, got 0x%02X)\n", + tc->key_type_usage, ktu); + exit(EXIT_FAILURE); } - ctx.vtable->append(&ctx.vtable, certs[u].data + v, w); - v += w; } - ctx.vtable->end_cert(&ctx.vtable); - } - status = ctx.vtable->end_chain(&ctx.vtable); - ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages); - /* - * Check key type and usage. - */ - if (ee_pkey != NULL) { - unsigned ktu; - - ktu = ee_pkey->key_type | usages; - if (tc->key_type_usage != (ktu & tc->key_type_usage)) { - fprintf(stderr, "wrong key type + usage" - " (expected 0x%02X, got 0x%02X)\n", - tc->key_type_usage, ktu); + /* + * Check results. Note that we may still get a public key if + * the path is "not trusted" (but otherwise fine). + */ + if (status != tc->status) { + fprintf(stderr, "wrong status (got %d, expected %d)\n", + status, tc->status); + exit(EXIT_FAILURE); + } + if (status == BR_ERR_X509_NOT_TRUSTED) { + ee_pkey = NULL; + } + if (!eqpkey(ee_pkey, ee_pkey_ref)) { + fprintf(stderr, "wrong EE public key\n"); exit(EXIT_FAILURE); } - } - - /* - * Check results. Note that we may still get a public key if - * the path is "not trusted" (but otherwise fine). - */ - if (status != tc->status) { - fprintf(stderr, "wrong status (got %d, expected %d)\n", - status, tc->status); - exit(EXIT_FAILURE); - } - if (status == BR_ERR_X509_NOT_TRUSTED) { - ee_pkey = NULL; - } - if (!eqpkey(ee_pkey, ee_pkey_ref)) { - fprintf(stderr, "wrong EE public key\n"); - exit(EXIT_FAILURE); - } - /* - * Check stack usage. - */ - for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) { - if (ctx.dp_stack[u - 1] != 0xA7C083FE) { - if (max_dp_usage < u) { - max_dp_usage = u; + /* + * Check stack usage. + */ + for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); + u > 0; u --) + { + if (ctx.dp_stack[u - 1] != 0xA7C083FE) { + if (max_dp_usage < u) { + max_dp_usage = u; + } + break; } - break; } - } - for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) { - if (ctx.rp_stack[u - 1] != 0xA7C083FE) { - if (max_rp_usage < u) { - max_rp_usage = u; + for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); + u > 0; u --) + { + if (ctx.rp_stack[u - 1] != 0xA7C083FE) { + if (max_rp_usage < u) { + max_rp_usage = u; + } + break; } - break; } } -- 2.17.1