From 99b7d32571d775f51aceec23fe5a47fc6b149f0f Mon Sep 17 00:00:00 2001 From: lhuang04 Date: Fri, 24 Apr 2026 08:54:55 -0700 Subject: [PATCH 1/2] Add MBEDTLS_SSL_TLS_HS_LARGE_MSG for large handshake message reassembly TLS handshake messages such as Certificate can exceed MBEDTLS_SSL_IN_CONTENT_LEN (16KB) when servers use certificate chains with many intermediate CAs or certificates with many SANs. The existing handshake defragmentation reassembles fragmented messages in-place, but is limited to the compile-time buffer size. Add a new compile-time option MBEDTLS_SSL_TLS_HS_LARGE_MSG that extends the existing in-place reassembly with dynamic buffer resizing. When enabled and configured at runtime via mbedtls_ssl_conf_max_handshake_msg_len(), the input buffer is proactively enlarged at the initial handshake fragment if the message will not fit. The enlarged buffer remains for the lifetime of the SSL context. This feature is TLS-only (not DTLS). Signed-off-by: Lin Huang --- include/mbedtls/mbedtls_config.h | 18 ++++++++++ include/mbedtls/ssl.h | 30 +++++++++++++++- library/ssl_msg.c | 62 +++++++++++++++++++++++++++++--- library/ssl_tls.c | 22 ++++++++++-- 4 files changed, 125 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index a38b61c147..f87426d921 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -848,6 +848,24 @@ */ //#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH +/** + * \def MBEDTLS_SSL_TLS_HS_LARGE_MSG + * + * Enable support for TLS handshake messages larger than + * MBEDTLS_SSL_IN_CONTENT_LEN. When enabled and configured at runtime + * via mbedtls_ssl_conf_max_handshake_msg_len(), the input buffer is + * dynamically resized during handshake reassembly if the reassembled + * message exceeds the compile-time buffer size. The enlarged buffer + * remains for the lifetime of the SSL context. + * + * This is useful when connecting to servers that send large Certificate + * messages (e.g., certificate chains with many intermediate CAs or + * certificates with many SANs). + * + * Requires: MBEDTLS_SSL_TLS_C + */ +//#define MBEDTLS_SSL_TLS_HS_LARGE_MSG + //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 or 384 bits) */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 3a69df5466..009da01dd1 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1557,6 +1557,11 @@ struct mbedtls_ssl_config { unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + size_t MBEDTLS_PRIVATE(max_handshake_msg_len); /*!< max reassembled handshake message + length (0 = use default buffer) */ +#endif + /** User data pointer or handle. * * The library sets this to \p 0 when creating a context and does not @@ -1705,7 +1710,7 @@ struct mbedtls_ssl_context { int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -4365,6 +4370,29 @@ void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) +/** + * \brief Set the maximum size of a reassembled TLS handshake message. + * + * When a reassembled handshake message is larger than + * MBEDTLS_SSL_IN_CONTENT_LEN, the input buffer will be + * dynamically resized to accommodate the full message. + * The enlarged buffer remains for the lifetime of the + * SSL context. + * + * This is TLS-only (not DTLS). + * + * \param conf SSL configuration + * \param max_handshake_msg_len Maximum handshake message length in bytes. + * Must be larger than MBEDTLS_SSL_IN_CONTENT_LEN and at most + * 0xFFFFFF (the maximum expressible in a TLS handshake header). + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_handshake_msg_len(mbedtls_ssl_config *conf, + size_t max_handshake_msg_len); +#endif /* MBEDTLS_SSL_TLS_HS_LARGE_MSG */ + #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Pick the ciphersuites order according to the second parameter diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 87d64788bd..c149d8079b 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -1856,7 +1856,7 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; @@ -2943,6 +2943,56 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) } ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl); + +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + /* Resize input buffer for handshake messages exceeding the default + * buffer. Must happen at the initial fragment, before the reassembly + * loop advances in_hdr past the buffered data. */ + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM && + ssl->conf->max_handshake_msg_len > 0 && + ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN) { + if (ssl->in_hslen > ssl->conf->max_handshake_msg_len) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("handshake message too large: %" + MBEDTLS_PRINTF_SIZET " > %" + MBEDTLS_PRINTF_SIZET, + ssl->in_hslen, + ssl->conf->max_handshake_msg_len)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* Allocate to the configured max so we resize at most once. */ + size_t needed = ssl->conf->max_handshake_msg_len + + MBEDTLS_SSL_IN_BUFFER_LEN; + size_t cur_buf_len = ssl->in_buf_len; + + if (needed > cur_buf_len) { + size_t in_hdr_offset = (size_t) (ssl->in_hdr - ssl->in_buf); + + unsigned char *new_buf = mbedtls_calloc(1, needed); + if (new_buf == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("alloc(%" MBEDTLS_PRINTF_SIZET + " bytes) failed", needed)); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(new_buf, ssl->in_buf, cur_buf_len); + mbedtls_zeroize_and_free(ssl->in_buf, cur_buf_len); + + ssl->in_buf = new_buf; + ssl->in_buf_len = needed; + + /* Restore in_hdr and derive all other pointers. */ + ssl->in_hdr = ssl->in_buf + in_hdr_offset; + mbedtls_ssl_update_in_pointers(ssl); + + MBEDTLS_SSL_DEBUG_MSG(2, + ("Reallocating in_buf to %" + MBEDTLS_PRINTF_SIZET, needed)); + } + } +#endif /* MBEDTLS_SSL_TLS_HS_LARGE_MSG */ } MBEDTLS_SSL_DEBUG_MSG(3, ("handshake message: msglen =" @@ -3107,7 +3157,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) * after the explicit IV, but here we move it to start where the * IV was. */ -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) size_t const in_buf_len = ssl->in_buf_len; #else size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; @@ -3142,7 +3192,10 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) ssl->in_hdr = reassembled_record_start; mbedtls_ssl_update_in_pointers(ssl); - /* Update the record length in the fully reassembled record */ +#if !defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + /* Write reassembled length to the 2-byte record header field. + * Skipped when TLS_HS_LARGE_MSG is enabled because the value + * is never read back (all processing uses in_msglen). */ if (ssl->in_msglen > 0xffff) { MBEDTLS_SSL_DEBUG_MSG(1, ("Shouldn't happen: in_msglen=%" @@ -3151,6 +3204,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0); +#endif size_t record_len = mbedtls_ssl_in_hdr_len(ssl) + ssl->in_msglen; (void) record_len; @@ -4583,7 +4637,7 @@ static int ssl_load_buffered_record(mbedtls_ssl_context *ssl) unsigned char *rec; size_t rec_len; unsigned rec_epoch; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e8a44f834c..3a4b69e01d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1196,7 +1196,7 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, /* Set to NULL in case of an error condition */ ssl->out_buf = NULL; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) ssl->in_buf_len = in_buf_len; #endif ssl->in_buf = mbedtls_calloc(1, in_buf_len); @@ -1238,6 +1238,8 @@ error: #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->in_buf_len = 0; ssl->out_buf_len = 0; +#elif defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + ssl->in_buf_len = 0; #endif ssl->in_buf = NULL; ssl->out_buf = NULL; @@ -1270,6 +1272,9 @@ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; size_t out_buf_len = ssl->out_buf_len; +#elif defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; @@ -2653,6 +2658,19 @@ int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_co } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) +int mbedtls_ssl_conf_max_handshake_msg_len(mbedtls_ssl_config *conf, + size_t max_handshake_msg_len) +{ + if (max_handshake_msg_len <= MBEDTLS_SSL_IN_CONTENT_LEN || + max_handshake_msg_len > 0xFFFFFFu) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + conf->max_handshake_msg_len = max_handshake_msg_len; + return 0; +} +#endif /* MBEDTLS_SSL_TLS_HS_LARGE_MSG */ + void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy) { conf->allow_legacy_renegotiation = allow_legacy; @@ -5165,7 +5183,7 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl) } if (ssl->in_buf != NULL) { -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; From a5a281ab6c557a48c2759d81f5f5352b55907ac1 Mon Sep 17 00:00:00 2001 From: lhuang04 Date: Fri, 24 Apr 2026 08:54:55 -0700 Subject: [PATCH 2/2] Add tests and CLI plumbing for MBEDTLS_SSL_TLS_HS_LARGE_MSG Add unit tests: - send_large_fragmented_hello_with_resize() test function - 6 test cases: resize success, exceeds max, 2x buffer, >64KB, first_frag=1024, and configured max rejection Add ssl-opt.sh integration tests: - TLS 1.2 and TLS 1.3 large cert with buffer resize - TLS 1.2 with explicit -split_send_frag 256 - Large cert fixture (26KB EC cert with 700 SANs, signed by test-ca2) Add CLI plumbing: - max_hs_msg_len= option for ssl_server2 and ssl_client2 Add ChangeLog.d entry. Signed-off-by: Lin Huang --- ChangeLog.d/tls-hs-large-msg.txt | 8 + programs/ssl/ssl_client2.c | 24 + programs/ssl/ssl_server2.c | 24 + tests/data_files/server_large.crt | 550 ++++++++++++++++++++ tests/data_files/server_large.key | 8 + tests/ssl-opt.sh | 33 ++ tests/suites/test_suite_ssl.function | 108 ++++ tests/suites/test_suite_ssl.tls-defrag.data | 37 ++ 8 files changed, 792 insertions(+) create mode 100644 ChangeLog.d/tls-hs-large-msg.txt create mode 100644 tests/data_files/server_large.crt create mode 100644 tests/data_files/server_large.key diff --git a/ChangeLog.d/tls-hs-large-msg.txt b/ChangeLog.d/tls-hs-large-msg.txt new file mode 100644 index 0000000000..5cd580ef8b --- /dev/null +++ b/ChangeLog.d/tls-hs-large-msg.txt @@ -0,0 +1,8 @@ +Features + * Add support for TLS handshake messages larger than + MBEDTLS_SSL_IN_CONTENT_LEN via the new compile-time option + MBEDTLS_SSL_TLS_HS_LARGE_MSG and the runtime configuration + function mbedtls_ssl_conf_max_handshake_msg_len(). When enabled, + the input buffer is dynamically resized during handshake + reassembly to accommodate large messages such as Certificate + chains with many intermediate CAs or many SANs. diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index fc00473cfc..02ab60544e 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -229,6 +229,14 @@ int main(void) #define USAGE_MAX_FRAG_LEN "" #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) +#define USAGE_MAX_HS_MSG_LEN \ + " max_hs_msg_len=%%d default: 0 (disabled)\n" \ + " max reassembled handshake message size\n" +#else +#define USAGE_MAX_HS_MSG_LEN "" +#endif /* MBEDTLS_SSL_TLS_HS_LARGE_MSG */ + #if defined(MBEDTLS_SSL_ALPN) #define USAGE_ALPN \ " alpn=%%s default: \"\" (disabled)\n" \ @@ -422,6 +430,7 @@ int main(void) USAGE_TICKETS \ USAGE_EAP_TLS \ USAGE_MAX_FRAG_LEN \ + USAGE_MAX_HS_MSG_LEN \ USAGE_CONTEXT_CRT_CB \ USAGE_ALPN \ USAGE_EMS \ @@ -501,6 +510,7 @@ struct options { int set_hostname; /* call mbedtls_ssl_set_hostname()? */ /* 0=no, 1=yes, -1=NULL */ unsigned char mfl_code; /* code for maximum fragment length */ + int max_hs_msg_len; /* max reassembled handshake message len */ int trunc_hmac; /* negotiate truncated hmac or not */ int recsplit; /* enable record splitting? */ int reconnect; /* attempt to resume session */ @@ -937,6 +947,7 @@ int main(int argc, char *argv[]) opt.auth_mode = DFL_AUTH_MODE; opt.set_hostname = DFL_SET_HOSTNAME; opt.mfl_code = DFL_MFL_CODE; + opt.max_hs_msg_len = 0; opt.trunc_hmac = DFL_TRUNC_HMAC; opt.recsplit = DFL_RECSPLIT; opt.reconnect = DFL_RECONNECT; @@ -1345,6 +1356,8 @@ usage: } else { goto usage; } + } else if (strcmp(p, "max_hs_msg_len") == 0) { + opt.max_hs_msg_len = atoi(q); } else if (strcmp(p, "trunc_hmac") == 0) { switch (atoi(q)) { case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break; @@ -1845,6 +1858,17 @@ usage: } #endif +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + if (opt.max_hs_msg_len > 0) { + if ((ret = mbedtls_ssl_conf_max_handshake_msg_len( + &conf, (size_t) opt.max_hs_msg_len)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_conf_max_handshake_msg_len" + " returned %d\n\n", ret); + goto exit; + } + } +#endif + #if defined(MBEDTLS_SSL_DTLS_SRTP) const mbedtls_ssl_srtp_profile forced_profile[] = { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET }; diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 79cbad877d..e5227de896 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -344,6 +344,14 @@ int main(void) #define USAGE_MAX_FRAG_LEN "" #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) +#define USAGE_MAX_HS_MSG_LEN \ + " max_hs_msg_len=%%d default: 0 (disabled)\n" \ + " max reassembled handshake message size\n" +#else +#define USAGE_MAX_HS_MSG_LEN "" +#endif /* MBEDTLS_SSL_TLS_HS_LARGE_MSG */ + #if defined(MBEDTLS_SSL_ALPN) #define USAGE_ALPN \ " alpn=%%s default: \"\" (disabled)\n" \ @@ -552,6 +560,7 @@ int main(void) USAGE_CACHE \ USAGE_CACHE_TIME \ USAGE_MAX_FRAG_LEN \ + USAGE_MAX_HS_MSG_LEN \ USAGE_ALPN \ USAGE_EMS \ USAGE_ETM \ @@ -652,6 +661,7 @@ struct options { int cert_req_ca_list; /* should we send the CA list? */ int cert_req_dn_hint; /* mode to set DN hints for CA list to send */ unsigned char mfl_code; /* code for maximum fragment length */ + int max_hs_msg_len; /* max reassembled handshake message len */ int trunc_hmac; /* accept truncated hmac? */ int tickets; /* enable / disable session tickets */ int dummy_ticket; /* enable / disable dummy ticket generator */ @@ -1720,6 +1730,7 @@ int main(int argc, char *argv[]) opt.cert_req_ca_list = DFL_CERT_REQ_CA_LIST; opt.cert_req_dn_hint = DFL_CERT_REQ_DN_HINT; opt.mfl_code = DFL_MFL_CODE; + opt.max_hs_msg_len = 0; opt.trunc_hmac = DFL_TRUNC_HMAC; opt.tickets = DFL_TICKETS; opt.dummy_ticket = DFL_DUMMY_TICKET; @@ -2127,6 +2138,8 @@ usage: } else { goto usage; } + } else if (strcmp(p, "max_hs_msg_len") == 0) { + opt.max_hs_msg_len = atoi(q); } else if (strcmp(p, "alpn") == 0) { opt.alpn_string = q; } else if (strcmp(p, "trunc_hmac") == 0) { @@ -2805,6 +2818,17 @@ usage: } #endif +#if defined(MBEDTLS_SSL_TLS_HS_LARGE_MSG) + if (opt.max_hs_msg_len > 0) { + if ((ret = mbedtls_ssl_conf_max_handshake_msg_len( + &conf, (size_t) opt.max_hs_msg_len)) != 0) { + mbedtls_printf(" failed\n ! mbedtls_ssl_conf_max_handshake_msg_len" + " returned %d\n\n", ret); + goto exit; + } + } +#endif + #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (opt.cid_enabled == 1 || opt.cid_enabled_renego == 1) { if (opt.cid_enabled == 1 && diff --git a/tests/data_files/server_large.crt b/tests/data_files/server_large.crt new file mode 100644 index 0000000000..fbf9e676db --- /dev/null +++ b/tests/data_files/server_large.crt @@ -0,0 +1,550 @@ +-----BEGIN CERTIFICATE----- +MIJmrDCCZjOgAwIBAgIUXzD0yO+zDtqd8eJj27jEQJgLgDEwCgYIKoZIzj0EAwIw +PjELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xh +cnNzbCBUZXN0IEVDIENBMCAXDTI2MDQwOTE0MDgzMFoYDzIxMjYwMzE2MTQwODMw +WjA0MQswCQYDVQQGEwJOTDERMA8GA1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxv +Y2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMfzOufKuITJ3NBp2lD0 +68+5hcL8JE6a9/lvMtwXsmpBd6XvVsHc15BTGfni86AczV9HKUM6OmaS8wkQ7znI +Z+ujgmUVMIJlETCCZM0GA1UdEQSCZMQwgmTAgglsb2NhbGhvc3SHBH8AAAGHEAAA +AAAAAAAAAAAAAAAAAAGCIWhvc3QyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIhaG9zdDMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiFob3N0NC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CIWhvc3Q1LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIhaG9zdDYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiFo +b3N0Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CIWhvc3Q4LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIhaG9zdDkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MTAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MTIubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MTMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MTQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MTYubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MTcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MTgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MTkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjAubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MjIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MjMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjQubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MjYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MjcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjgubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MjkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MzAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MzEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MzIubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MzMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MzQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MzUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MzYubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0MzcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0MzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +MzkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDAubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NDIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NDMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDQubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NDYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NDcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDgubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NDkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NTAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NTIubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NTMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NTQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NTYubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NTcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NTgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NTkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjAubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NjIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NjMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjQubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NjYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NjcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjgubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NjkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NzAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NzEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NzIubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NzMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NzQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NzUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NzYubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0NzcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0NzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +NzkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODAubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0ODIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +ODMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODQubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0ODYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +ODcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODgubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0ODkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0OTAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +OTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0OTIubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0OTMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0OTQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +OTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0OTYubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiJob3N0OTcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiJob3N0OTgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiJob3N0 +OTkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTAwLmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDEwMS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QxMDIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MTAzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDEwNC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMDUubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0MTA2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDEwNy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMDgu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTA5LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDExMC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QxMTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MTEyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDExMy5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMTQubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MTE1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDExNi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMTcubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTE4LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDExOS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QxMjAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTIx +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDEyMi5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMjMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MTI0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDEyNS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMjYubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTI3LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDEyOC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QxMjkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTMwLmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDEzMS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QxMzIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0MTMzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDEz +NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxMzUubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTM2LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDEzNy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QxMzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTM5Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE0MC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QxNDEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0MTQyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE0My5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNDQubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0MTQ1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDE0Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qx +NDcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTQ4LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE0OS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QxNTAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MTUxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE1Mi5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNTMubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0MTU0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDE1NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNTYu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTU3LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDE1OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QxNTkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MTYwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE2MS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNjIubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MTYzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDE2NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNjUubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTY2LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDE2Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QxNjgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTY5 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE3MC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNzEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MTcyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDE3My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxNzQubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTc1LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDE3Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QxNzcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTc4Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE3OS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QxODAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0MTgxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE4 +Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxODMubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTg0LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDE4NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QxODYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTg3Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE4OC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QxODkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0MTkwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE5MS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QxOTIubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0MTkzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDE5NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qx +OTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MTk2LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDE5Ny5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QxOTgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MTk5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIwMC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMDEubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0MjAyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDIwMy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMDQu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjA1LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDIwNi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QyMDcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MjA4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIwOS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMTAubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MjExLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDIxMi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMTMubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjE0LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDIxNS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QyMTYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjE3 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIxOC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMTkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MjIwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDIyMS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMjIubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjIzLmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDIyNC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QyMjUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjI2Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIyNy5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QyMjgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0MjI5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIz +MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyMzEubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjMyLmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDIzMy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QyMzQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjM1Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIzNi5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QyMzcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0MjM4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDIzOS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNDAubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0MjQxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDI0Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qy +NDMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjQ0LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI0NS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QyNDYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MjQ3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI0OC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNDkubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0MjUwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDI1MS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNTIu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjUzLmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDI1NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QyNTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MjU2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI1Ny5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNTgubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MjU5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDI2MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNjEubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjYyLmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDI2My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QyNjQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjY1 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI2Ni5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNjcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MjY4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDI2OS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNzAubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjcxLmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDI3Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QyNzMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Mjc0Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI3NS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QyNzYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0Mjc3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI3 +OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyNzkubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjgwLmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDI4MS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QyODIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjgzLmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI4NC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QyODUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0Mjg2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI4Ny5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyODgubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0Mjg5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDI5MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qy +OTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MjkyLmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI5My5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QyOTQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0Mjk1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDI5Ni5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QyOTcubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0Mjk4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDI5OS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMDAu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzAxLmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDMwMi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QzMDMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MzA0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMwNS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMDYubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MzA3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDMwOC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMDkubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzEwLmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDMxMS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QzMTIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzEz +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMxNC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMTUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MzE2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDMxNy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMTgubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzE5LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDMyMC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QzMjEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzIyLmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMyMy5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QzMjQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0MzI1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMy +Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMjcubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzI4LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDMyOS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QzMzAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzMxLmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMzMi5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QzMzMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0MzM0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDMzNS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzMzYubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0MzM3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDMzOC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qz +MzkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzQwLmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM0MS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QzNDIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MzQzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM0NC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNDUubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0MzQ2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDM0Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNDgu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzQ5LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDM1MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QzNTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +MzUyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM1My5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNTQubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0MzU1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDM1Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNTcubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzU4LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDM1OS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3QzNjAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzYx +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM2Mi5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNjMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0MzY0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDM2NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNjYubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzY3LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDM2OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3QzNjkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0MzcwLmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM3MS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3QzNzIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0MzczLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM3 +NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzNzUubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Mzc2LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDM3Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3QzNzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Mzc5Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM4MC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3QzODEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0MzgyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM4My5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzODQubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0Mzg1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDM4Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Qz +ODcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Mzg4LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM4OS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3QzOTAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0MzkxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDM5Mi5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzOTMubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0Mzk0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDM5NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3QzOTYu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Mzk3LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDM5OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3QzOTkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NDAwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQwMS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MDIubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NDAzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDQwNC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MDUubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDA2LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDQwNy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q0MDgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDA5 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQxMC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MTEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NDEyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDQxMy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MTQubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDE1LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDQxNi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q0MTcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDE4Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQxOS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q0MjAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NDIxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQy +Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MjMubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDI0LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDQyNS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q0MjYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDI3Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQyOC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q0MjkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NDMwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQzMS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0MzIubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NDMzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDQzNC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0 +MzUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDM2LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQzNy5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q0MzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0NDM5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ0MC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NDEubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NDQyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDQ0My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NDQu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDQ1LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ0Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q0NDcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NDQ4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ0OS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NTAubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NDUxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDQ1Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NTMubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDU0LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDQ1NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q0NTYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDU3 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ1OC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NTkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NDYwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDQ2MS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NjIubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDYzLmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDQ2NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q0NjUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDY2Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ2Ny5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q0NjgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NDY5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ3 +MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0NzEubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDcyLmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDQ3My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q0NzQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDc1Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ3Ni5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q0NzcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NDc4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ3OS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0ODAubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NDgxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDQ4Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0 +ODMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDg0LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ4NS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q0ODYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0NDg3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ4OC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0ODkubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NDkwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDQ5MS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0OTIu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NDkzLmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ5NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q0OTUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NDk2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDQ5Ny5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q0OTgubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NDk5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDUwMC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MDEubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTAyLmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDUwMy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q1MDQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTA1 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUwNi5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MDcubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NTA4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDUwOS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MTAubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTExLmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDUxMi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q1MTMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTE0Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUxNS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q1MTYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NTE3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUx +OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MTkubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTIwLmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDUyMS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q1MjIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTIzLmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUyNC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q1MjUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NTI2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUyNy5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MjgubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NTI5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDUzMC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1 +MzEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTMyLmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUzMy5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q1MzQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0NTM1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDUzNi5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1MzcubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NTM4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDUzOS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NDAu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTQxLmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDU0Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q1NDMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NTQ0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU0NS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NDYubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NTQ3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDU0OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NDkubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTUwLmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDU1MS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q1NTIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTUz +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU1NC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NTUubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NTU2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDU1Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NTgubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTU5LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDU2MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q1NjEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTYyLmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU2My5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q1NjQubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NTY1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU2 +Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NjcubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTY4LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDU2OS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q1NzAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTcxLmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU3Mi5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q1NzMubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NTc0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU3NS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1NzYubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NTc3LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDU3OC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1 +NzkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTgwLmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU4MS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q1ODIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0NTgzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU4NC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1ODUubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NTg2LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDU4Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1ODgu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTg5LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDU5MC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q1OTEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NTkyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDU5My5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1OTQubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NTk1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDU5Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q1OTcubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NTk4LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDU5OS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q2MDAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjAx +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYwMi5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MDMubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NjA0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDYwNS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MDYubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjA3LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDYwOC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q2MDkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjEwLmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYxMS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q2MTIubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NjEzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYx +NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MTUubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjE2LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDYxNy5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q2MTgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjE5Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYyMC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q2MjEubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NjIyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYyMy5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MjQubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NjI1LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDYyNi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2 +MjcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjI4LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYyOS5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q2MzAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0NjMxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDYzMi5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MzMubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NjM0LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDYzNS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2MzYu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjM3LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDYzOC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q2MzkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +NjQwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY0MS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NDIubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NjQzLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDY0NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NDUubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjQ2LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDY0Ny5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q2NDgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjQ5 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY1MC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NTEubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NjUyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9z +dDY1My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NTQubGFyZ2Ut +Y2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjU1LmxhcmdlLWNlcnQtdGVzdC5l +eGFtcGxlLmNvbYIjaG9zdDY1Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22C +I2hvc3Q2NTcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjU4Lmxh +cmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY1OS5sYXJnZS1jZXJ0LXRl +c3QuZXhhbXBsZS5jb22CI2hvc3Q2NjAubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUu +Y29tgiNob3N0NjYxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY2 +Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NjMubGFyZ2UtY2Vy +dC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjY0LmxhcmdlLWNlcnQtdGVzdC5leGFt +cGxlLmNvbYIjaG9zdDY2NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hv +c3Q2NjYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0NjY3Lmxhcmdl +LWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY2OC5sYXJnZS1jZXJ0LXRlc3Qu +ZXhhbXBsZS5jb22CI2hvc3Q2NjkubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29t +giNob3N0NjcwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY3MS5s +YXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2NzIubGFyZ2UtY2VydC10 +ZXN0LmV4YW1wbGUuY29tgiNob3N0NjczLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxl +LmNvbYIjaG9zdDY3NC5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2 +NzUubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Njc2LmxhcmdlLWNl +cnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY3Ny5sYXJnZS1jZXJ0LXRlc3QuZXhh +bXBsZS5jb22CI2hvc3Q2NzgubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNo +b3N0Njc5LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY4MC5sYXJn +ZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2ODEubGFyZ2UtY2VydC10ZXN0 +LmV4YW1wbGUuY29tgiNob3N0NjgyLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNv +bYIjaG9zdDY4My5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2ODQu +bGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Njg1LmxhcmdlLWNlcnQt +dGVzdC5leGFtcGxlLmNvbYIjaG9zdDY4Ni5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBs +ZS5jb22CI2hvc3Q2ODcubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0 +Njg4LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY4OS5sYXJnZS1j +ZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2OTAubGFyZ2UtY2VydC10ZXN0LmV4 +YW1wbGUuY29tgiNob3N0NjkxLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIj +aG9zdDY5Mi5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2OTMubGFy +Z2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Njk0LmxhcmdlLWNlcnQtdGVz +dC5leGFtcGxlLmNvbYIjaG9zdDY5NS5sYXJnZS1jZXJ0LXRlc3QuZXhhbXBsZS5j +b22CI2hvc3Q2OTYubGFyZ2UtY2VydC10ZXN0LmV4YW1wbGUuY29tgiNob3N0Njk3 +LmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbYIjaG9zdDY5OC5sYXJnZS1jZXJ0 +LXRlc3QuZXhhbXBsZS5jb22CI2hvc3Q2OTkubGFyZ2UtY2VydC10ZXN0LmV4YW1w +bGUuY29tgiNob3N0NzAwLmxhcmdlLWNlcnQtdGVzdC5leGFtcGxlLmNvbTAdBgNV +HQ4EFgQUT/LulT4eBlKiF9DBf/rzb9ND7a0wHwYDVR0jBBgwFoAUnW0gJEkBPyvL +eLUZvH4kydv7NnwwCgYIKoZIzj0EAwIDZwAwZAIwO0A+XYMxz3x1F+mlSqd1B3DY +Lm6kR34T/Iaun6Hbd+pikNTHm8F+kL30HhO/3XsyAjAN1VjwD6f4alozePRsvBXA +5R3h+ggKWpU6dp9B56gkDObUJN3rLoVEimNhtPZstiI= +-----END CERTIFICATE----- diff --git a/tests/data_files/server_large.key b/tests/data_files/server_large.key new file mode 100644 index 0000000000..6155b8987d --- /dev/null +++ b/tests/data_files/server_large.key @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIDEE1YCrXw4pD9BJGZWPXM3VUTwE324im85EfDKaA212oAoGCCqGSM49 +AwEHoUQDQgAEx/M658q4hMnc0GnaUPTrz7mFwvwkTpr3+W8y3BeyakF3pe9WwdzX +kFMZ+eLzoBzNX0cpQzo6ZpLzCRDvOchn6w== +-----END EC PRIVATE KEY----- diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 47ff800ed1..c06ac45839 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -14318,6 +14318,39 @@ run_test "Handshake defragmentation on client: len=4, server-initiated renego -c "found renegotiation extension" \ -c "=> renegotiate" +# Test large handshake message with buffer resize (MBEDTLS_SSL_TLS_HS_LARGE_MSG) +# The OpenSSL server sends a large certificate (>16KB) to the Mbed TLS client, +# which must resize its input buffer to reassemble the fragmented handshake message. +# Large cert fixtures are in tests/data_files/ (not the framework submodule). +LARGE_DATA_FILES_PATH=../tests/data_files + +requires_config_enabled MBEDTLS_SSL_TLS_HS_LARGE_MSG +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "Handshake defragmentation on client: large cert with buffer resize (TLS 1.2)" \ + "$O_NEXT_SRV -tls1_2 -cert $LARGE_DATA_FILES_PATH/server_large.crt -key $LARGE_DATA_FILES_PATH/server_large.key" \ + "$P_CLI debug_level=4 max_hs_msg_len=131072 ca_file=$DATA_FILES_PATH/test-ca2.crt" \ + 0 \ + -c "Reallocating in_buf" \ + -c "handshake fragment" + +requires_config_enabled MBEDTLS_SSL_TLS_HS_LARGE_MSG +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +run_test "Handshake defragmentation on client: large cert with buffer resize (TLS 1.3)" \ + "$O_NEXT_SRV -tls1_3 -cert $LARGE_DATA_FILES_PATH/server_large.crt -key $LARGE_DATA_FILES_PATH/server_large.key" \ + "$P_CLI debug_level=4 max_hs_msg_len=131072 ca_file=$DATA_FILES_PATH/test-ca2.crt" \ + 0 \ + -c "Reallocating in_buf" \ + -c "handshake fragment" + +requires_config_enabled MBEDTLS_SSL_TLS_HS_LARGE_MSG +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "Handshake defragmentation on client: large cert, split_send_frag=256" \ + "$O_NEXT_SRV -tls1_2 -split_send_frag 256 -cert $LARGE_DATA_FILES_PATH/server_large.crt -key $LARGE_DATA_FILES_PATH/server_large.key" \ + "$P_CLI debug_level=4 max_hs_msg_len=131072 ca_file=$DATA_FILES_PATH/test-ca2.crt" \ + 0 \ + -c "Reallocating in_buf" \ + -c "initial handshake fragment" + # Test heap memory usage after handshake requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 requires_config_enabled MBEDTLS_MEMORY_DEBUG diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 39457c9047..cd957a5347 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5725,6 +5725,114 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY:MBEDTLS_SSL_TLS_HS_LARGE_MSG */ +void send_large_fragmented_hello_with_resize(int hs_len_int, + int first_frag_content_len_int, + int max_hs_msg_len_int, + char *log_pattern, + int expected_ret) +{ + /* Like send_large_fragmented_hello, but configures + * mbedtls_ssl_conf_max_handshake_msg_len() to allow the server to + * dynamically resize its input buffer for large handshake messages. */ + enum { BUFFSIZE = 16384 }; + mbedtls_test_ssl_endpoint server, client; + mbedtls_platform_zeroize(&server, sizeof(server)); + mbedtls_platform_zeroize(&client, sizeof(client)); + + mbedtls_test_handshake_test_options options; + mbedtls_test_init_handshake_options(&options); + + mbedtls_test_ssl_log_pattern srv_pattern; + memset(&srv_pattern, 0, sizeof(srv_pattern)); + + unsigned char *first_frag = NULL; + int ret = -1; + + size_t hs_len = (size_t) hs_len_int; + size_t first_frag_content_len = (size_t) first_frag_content_len_int; + + PSA_INIT(); + + srv_pattern.pattern = log_pattern; + options.srv_log_obj = &srv_pattern; + options.srv_log_fun = mbedtls_test_ssl_log_analyzer; + mbedtls_debug_set_threshold(2); + + options.pk_alg = MBEDTLS_PK_ECDSA; + + ret = mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER, + &options); + TEST_EQUAL(ret, 0); + + /* Configure max handshake message length for resize */ + if (max_hs_msg_len_int > 0) { + ret = mbedtls_ssl_conf_max_handshake_msg_len( + &server.conf, (size_t) max_hs_msg_len_int); + TEST_EQUAL(ret, 0); + } + + ret = mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT, + &options); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&server.socket, &client.socket, + BUFFSIZE); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, + MBEDTLS_SSL_CLIENT_HELLO); + TEST_EQUAL(ret, 0); + + /* Prepare initial fragment */ + const size_t first_len = 5 + 4 + first_frag_content_len; + TEST_CALLOC(first_frag, first_len); + unsigned char *p = first_frag; + *p++ = 0x16; + *p++ = 0x03; + *p++ = 0x03; + *p++ = (unsigned char) (((4 + first_frag_content_len) >> 8) & 0xff); + *p++ = (unsigned char) (((4 + first_frag_content_len) >> 0) & 0xff); + *p++ = 0x01; + *p++ = (unsigned char) ((hs_len >> 16) & 0xff); + *p++ = (unsigned char) ((hs_len >> 8) & 0xff); + *p++ = (unsigned char) ((hs_len >> 0) & 0xff); + memset(p, 0x2a, first_frag_content_len); + + ret = mbedtls_test_mock_tcp_send_b(&client.socket, first_frag, first_len); + TEST_ASSERT(ret >= 0 && (size_t) ret == first_len); + + ret = mbedtls_ssl_handshake_step(&server.ssl); + /* The initial fragment may already trigger a rejection (e.g., when + * in_hslen exceeds the configured max). In that case, skip the loop. */ + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + const unsigned char next[] = { + 0x16, 0x03, 0x03, 0x00, 0x01, + 0x2a, + }; + for (size_t left = hs_len - first_frag_content_len; left != 0; left--) { + ret = mbedtls_test_mock_tcp_send_b(&client.socket, next, sizeof(next)); + TEST_ASSERT(ret >= 0 && (size_t) ret == sizeof(next)); + + ret = mbedtls_ssl_handshake_step(&server.ssl); + if (ret != MBEDTLS_ERR_SSL_WANT_READ) { + break; + } + } + } + TEST_EQUAL(ret, expected_ret); + TEST_ASSERT(srv_pattern.counter >= 1); + +exit: + mbedtls_test_free_handshake_options(&options); + mbedtls_test_ssl_endpoint_free(&server); + mbedtls_test_ssl_endpoint_free(&client); + mbedtls_debug_set_threshold(0); + mbedtls_free(first_frag); + PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP*/ void send_invalid_sig_alg(int sig, int hash, int expected_ret) { diff --git a/tests/suites/test_suite_ssl.tls-defrag.data b/tests/suites/test_suite_ssl.tls-defrag.data index 7817c4f501..88715f3f57 100644 --- a/tests/suites/test_suite_ssl.tls-defrag.data +++ b/tests/suites/test_suite_ssl.tls-defrag.data @@ -213,3 +213,40 @@ send_large_fragmented_hello:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - # fit in the buffer, but still add a test just in case. Send large fragmented ClientHello: length doesn't fit in two bytes send_large_fragmented_hello:0x10000:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +# Tests for MBEDTLS_SSL_TLS_HS_LARGE_MSG: buffer resize during reassembly. +# When max_handshake_msg_len is configured, messages that exceed the default +# buffer are reassembled after a proactive resize. "Success" is inferred when +# reassembly completes and the version check fails (dummy 0x2a content). + +# Message that previously failed ("requesting more data than fits") now +# succeeds because the buffer is resized to accommodate it. +Send large fragmented ClientHello with resize: previously too large, now fits +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 3:0:MBEDTLS_SSL_IN_BUFFER_LEN * 2:"Reallocating in_buf":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION + +# Message exactly at the old limit that needed overhead space — now fits. +Send large fragmented ClientHello with resize: overhead case now fits +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_HEADER_LEN - 4:0:MBEDTLS_SSL_IN_BUFFER_LEN * 2:"Reallocating in_buf":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION + +# Message significantly larger than buffer (2x), with sufficient max configured. +Send large fragmented ClientHello with resize: 2x buffer size +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:MBEDTLS_SSL_IN_BUFFER_LEN * 2:0:MBEDTLS_SSL_IN_BUFFER_LEN * 3:"Reallocating in_buf":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION + +# Message exceeds the configured max — rejected at initial fragment. +Send large fragmented ClientHello with resize: exceeds configured max +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:MBEDTLS_SSL_IN_BUFFER_LEN * 2:0:MBEDTLS_SSL_IN_BUFFER_LEN:"handshake message too large":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +# Message larger than 0xFFFF (64KB) — tests 2-byte record header capping. +Send large fragmented ClientHello with resize: larger than 64KB +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:0x10001:0:0x20000:"Reallocating in_buf":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION + +# Same as 2x buffer size, but with a non-zero initial fragment (1024 bytes of +# handshake content in the first record, then 1-byte fragments for the rest). +Send large fragmented ClientHello with resize: 2x buffer, first_frag=1024 +depends_on:MBEDTLS_SSL_TLS_HS_LARGE_MSG +send_large_fragmented_hello_with_resize:MBEDTLS_SSL_IN_BUFFER_LEN * 2:1024:MBEDTLS_SSL_IN_BUFFER_LEN * 3:"Reallocating in_buf":MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION