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/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 00e28442d6..d691b6357d 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1566,6 +1566,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 @@ -1721,7 +1726,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) @@ -4382,6 +4387,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 0195576213..ba924da889 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1195,7 +1195,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); @@ -1237,6 +1237,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; @@ -1269,6 +1271,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; @@ -2660,6 +2665,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; @@ -5195,7 +5213,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; diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index ad87e225da..4bc21ea4f1 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -231,6 +231,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" \ @@ -425,6 +433,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 \ @@ -504,6 +513,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 */ @@ -941,6 +951,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; @@ -1350,6 +1361,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; @@ -1859,6 +1872,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 b5cdc817b8..2bf74fe94e 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -345,6 +345,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" \ @@ -550,6 +558,7 @@ int main(void) USAGE_CACHE \ USAGE_CACHE_TIME \ USAGE_MAX_FRAG_LEN \ + USAGE_MAX_HS_MSG_LEN \ USAGE_ALPN \ USAGE_EMS \ USAGE_ETM \ @@ -650,6 +659,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 */ @@ -1718,6 +1728,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; @@ -2125,6 +2136,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) { @@ -2803,6 +2816,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 e6ad70ee72..ffd831fdd9 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -14532,6 +14532,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 c1cf9bab86..e9e1b5e776 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6306,6 +6306,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