{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1745563261,
"reponame":"BearSSL",
"desc":"BearSSL TLS and crypto library",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/BearSSL",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"5c6c9786c547ce92707ee76802fa9c4c",
"commit": {"type":"commit",
"time": 1481387706,
"time_ofs": 60,
"oid_tree": { "oid": "8da69316923dfb17326ec8d724a600ccf7d85c56", "alias": []},
"oid":{ "oid": "e61ad42191511226309bad2cbde8cd9e8cc743cb", "alias": []},
"msg": "Added support for client certificates (both client-side and server-side, but still missing an ",
"sig_commit": { "git_time": { "time": 1481387706, "offset": 60 }, "name": "Thomas Pornin", "email": "pornin@bolet.org", "md5": "07ccc97c05f3fb80560ebc618a7de8bc" },
"sig_author": { "git_time": { "time": 1481387706, "offset": 60 }, "name": "Thomas Pornin", "email": "pornin@bolet.org", "md5": "07ccc97c05f3fb80560ebc618a7de8bc" }},
"body": "Added support for client certificates (both client-side and server-side, but still missing an API for extracting the client identity from the certificate).\n"
,
"diff": "diff --git a/Makefile b/Makefile\nindex 5eabd31..57a0867 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -54,7 +54,7 @@ OBJINT32 \u003d $(BUILD)/i32_add.o $(BUILD)/i32_bitlen.o $(BUILD)/i32_decmod.o $(BUIL\n OBJMAC \u003d $(BUILD)/hmac.o $(BUILD)/hmac_ct.o\n OBJRAND \u003d $(BUILD)/hmac_drbg.o\n OBJRSA \u003d $(BUILD)/rsa_i31_pkcs1_sign.o $(BUILD)/rsa_i31_pkcs1_vrfy.o $(BUILD)/rsa_i31_priv.o $(BUILD)/rsa_i31_pub.o $(BUILD)/rsa_i32_pkcs1_sign.o $(BUILD)/rsa_i32_pkcs1_vrfy.o $(BUILD)/rsa_i32_priv.o $(BUILD)/rsa_i32_pub.o $(BUILD)/rsa_ssl_decrypt.o\n-OBJSSL \u003d $(BUILD)/prf.o $(BUILD)/prf_md5sha1.o $(BUILD)/prf_sha256.o $(BUILD)/prf_sha384.o $(BUILD)/ssl_client.o $(BUILD)/ssl_client_full.o $(BUILD)/ssl_engine.o $(BUILD)/ssl_hashes.o $(BUILD)/ssl_hs_client.o $(BUILD)/ssl_hs_server.o $(BUILD)/ssl_io.o $(BUILD)/ssl_lru.o $(BUILD)/ssl_rec_cbc.o $(BUILD)/ssl_rec_gcm.o $(BUILD)/ssl_server.o $(BUILD)/ssl_server_mine2g.o $(BUILD)/ssl_server_minf2g.o $(BUILD)/ssl_server_minr2g.o $(BUILD)/ssl_server_minu2g.o $(BUILD)/ssl_server_minv2g.o $(BUILD)/ssl_server_full_ec.o $(BUILD)/ssl_server_full_rsa.o $(BUILD)/ssl_single_ec.o $(BUILD)/ssl_single_rsa.o\n+OBJSSL \u003d $(BUILD)/prf.o $(BUILD)/prf_md5sha1.o $(BUILD)/prf_sha256.o $(BUILD)/prf_sha384.o $(BUILD)/ssl_ccert_single_ec.o $(BUILD)/ssl_ccert_single_rsa.o $(BUILD)/ssl_client.o $(BUILD)/ssl_client_full.o $(BUILD)/ssl_engine.o $(BUILD)/ssl_hashes.o $(BUILD)/ssl_hs_client.o $(BUILD)/ssl_hs_server.o $(BUILD)/ssl_io.o $(BUILD)/ssl_lru.o $(BUILD)/ssl_rec_cbc.o $(BUILD)/ssl_rec_gcm.o $(BUILD)/ssl_server.o $(BUILD)/ssl_server_mine2g.o $(BUILD)/ssl_server_minf2g.o $(BUILD)/ssl_server_minr2g.o $(BUILD)/ssl_server_minu2g.o $(BUILD)/ssl_server_minv2g.o $(BUILD)/ssl_server_full_ec.o $(BUILD)/ssl_server_full_rsa.o $(BUILD)/ssl_scert_single_ec.o $(BUILD)/ssl_scert_single_rsa.o\n OBJSYMCIPHER \u003d $(BUILD)/aes_big_cbcdec.o $(BUILD)/aes_big_cbcenc.o $(BUILD)/aes_big_ctr.o $(BUILD)/aes_big_dec.o $(BUILD)/aes_big_enc.o $(BUILD)/aes_common.o $(BUILD)/aes_ct.o $(BUILD)/aes_ct64.o $(BUILD)/aes_ct64_cbcdec.o $(BUILD)/aes_ct64_cbcenc.o $(BUILD)/aes_ct64_ctr.o $(BUILD)/aes_ct64_dec.o $(BUILD)/aes_ct64_enc.o $(BUILD)/aes_ct_cbcdec.o $(BUILD)/aes_ct_cbcenc.o $(BUILD)/aes_ct_ctr.o $(BUILD)/aes_ct_dec.o $(BUILD)/aes_ct_enc.o $(BUILD)/aes_small_cbcdec.o $(BUILD)/aes_small_cbcenc.o $(BUILD)/aes_small_ctr.o $(BUILD)/aes_small_dec.o $(BUILD)/aes_small_enc.o $(BUILD)/des_ct.o $(BUILD)/des_ct_cbcdec.o $(BUILD)/des_ct_cbcenc.o $(BUILD)/des_support.o $(BUILD)/des_tab.o $(BUILD)/des_tab_cbcdec.o $(BUILD)/des_tab_cbcenc.o\n OBJX509 \u003d $(BUILD)/skey_decoder.o $(BUILD)/x509_decoder.o $(BUILD)/x509_knownkey.o $(BUILD)/x509_minimal.o\n OBJ \u003d $(OBJCODEC) $(OBJEC) $(OBJHASH) $(OBJINT31) $(OBJINT32) $(OBJMAC) $(OBJRAND) $(OBJRSA) $(OBJSSL) $(OBJSYMCIPHER) $(OBJX509)\n@@ -386,6 +386,12 @@ $(BUILD)/prf_sha256.o: src/ssl/prf_sha256.c $(HEADERS)\n $(BUILD)/prf_sha384.o: src/ssl/prf_sha384.c $(HEADERS)\n \t$(CC) $(CFLAGS) -c -o $(BUILD)/prf_sha384.o src/ssl/prf_sha384.c\n \n+$(BUILD)/ssl_ccert_single_ec.o: src/ssl/ssl_ccert_single_ec.c $(HEADERS)\n+\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_ccert_single_ec.o src/ssl/ssl_ccert_single_ec.c\n+\n+$(BUILD)/ssl_ccert_single_rsa.o: src/ssl/ssl_ccert_single_rsa.c $(HEADERS)\n+\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_ccert_single_rsa.o src/ssl/ssl_ccert_single_rsa.c\n+\n $(BUILD)/ssl_client.o: src/ssl/ssl_client.c $(HEADERS)\n \t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_client.o src/ssl/ssl_client.c\n \n@@ -440,11 +446,11 @@ $(BUILD)/ssl_server_full_ec.o: src/ssl/ssl_server_full_ec.c $(HEADERS)\n $(BUILD)/ssl_server_full_rsa.o: src/ssl/ssl_server_full_rsa.c $(HEADERS)\n \t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_full_rsa.o src/ssl/ssl_server_full_rsa.c\n \n-$(BUILD)/ssl_single_ec.o: src/ssl/ssl_single_ec.c $(HEADERS)\n-\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_ec.o src/ssl/ssl_single_ec.c\n+$(BUILD)/ssl_scert_single_ec.o: src/ssl/ssl_scert_single_ec.c $(HEADERS)\n+\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_scert_single_ec.o src/ssl/ssl_scert_single_ec.c\n \n-$(BUILD)/ssl_single_rsa.o: src/ssl/ssl_single_rsa.c $(HEADERS)\n-\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_rsa.o src/ssl/ssl_single_rsa.c\n+$(BUILD)/ssl_scert_single_rsa.o: src/ssl/ssl_scert_single_rsa.c $(HEADERS)\n+\t$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_scert_single_rsa.o src/ssl/ssl_scert_single_rsa.c\n \n $(BUILD)/aes_big_cbcdec.o: src/symcipher/aes_big_cbcdec.c $(HEADERS)\n \t$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_cbcdec.o src/symcipher/aes_big_cbcdec.c\ndiff --git a/inc/bearssl_ssl.h b/inc/bearssl_ssl.h\nindex 463e616..b038500 100644\n--- a/inc/bearssl_ssl.h\n+++ b/inc/bearssl_ssl.h\n@@ -191,9 +191,18 @@\n signature algorithm, hash function). */\n #define BR_ERR_INVALID_ALGORITHM 26\n \n-/** \u005cbrief SSL status: invalid signature on ServerKeyExchange message. */\n+/** \u005cbrief SSL status: invalid signature (on ServerKeyExchange from\n+ server, or in CertificateVerify from client). */\n #define BR_ERR_BAD_SIGNATURE 27\n \n+/** \u005cbrief SSL status: peer's public key does not have the proper type\n+ or is not allowed for requested operation. */\n+#define BR_ERR_WRONG_KEY_USAGE 28\n+\n+/** \u005cbrief SSL status: client did not send a certificate upon request,\n+ or the client certificate could not be validated. */\n+#define BR_ERR_NO_CLIENT_AUTH 29\n+\n /** \u005cbrief SSL status: I/O error or premature close on underlying\n transport stream. This error code is set only by the simplified\n I/O API (\u0022br_sslio_*\u0022). */\n@@ -769,12 +778,11 @@ typedef struct {\n \tuint32_t flags;\n \n \t/*\n-\t * Context variables for the handshake processor.\n-\t * The 'pad' must be large enough to accommodate an\n-\t * RSA-encrypted pre-master secret, or a RSA signature on\n-\t * key exchange parameters; since we want to support up to\n-\t * RSA-4096, this means at least 512 bytes.\n-\t * (Other pad usages require its length to be at least 256.)\n+\t * Context variables for the handshake processor. The 'pad' must\n+\t * be large enough to accommodate an RSA-encrypted pre-master\n+\t * secret, or an RSA signature; since we want to support up to\n+\t * RSA-4096, this means at least 512 bytes. (Other pad usages\n+\t * require its length to be at least 256.)\n \t */\n \tstruct {\n \t\tuint32_t *dp;\n@@ -826,6 +834,16 @@ typedef struct {\n \tconst br_x509_class **x509ctx;\n \n \t/*\n+\t * Certificate chain to send. This is used by both client and\n+\t * server, when they send their respective Certificate messages.\n+\t * If chain_len is 0, then chain may be NULL.\n+\t */\n+\tconst br_x509_certificate *chain;\n+\tsize_t chain_len;\n+\tconst unsigned char *cert_cur;\n+\tsize_t cert_len;\n+\n+\t/*\n \t * Pointers to implementations; left to NULL for unsupported\n \t * functions. For the raw hash functions, implementations are\n \t * referenced from the multihasher (mhash field).\n@@ -844,6 +862,8 @@ typedef struct {\n \tconst br_sslrec_in_gcm_class *igcm_in;\n \tconst br_sslrec_out_gcm_class *igcm_out;\n \tconst br_ec_impl *iec;\n+\tbr_rsa_pkcs1_vrfy irsavrfy;\n+\tbr_ecdsa_vrfy iecdsa;\n #endif\n } br_ssl_engine_context;\n \n@@ -909,7 +929,7 @@ br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)\n */\n #define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 \u003c\u003c 0)\n \n-/*\n+/**\n * \u005cbrief Behavioural flag: disable renegotiation.\n *\n * If this flag is set, then renegotiations are rejected unconditionally:\n@@ -919,6 +939,26 @@ br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)\n #define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 \u003c\u003c 1)\n \n /**\n+ * \u005cbrief Behavioural flag: tolerate lack of client authentication.\n+ *\n+ * If this flag is set in a server and the server requests a client\n+ * certificate, but the authentication fails (the client does not send\n+ * a certificate, or the client's certificate chain cannot be validated),\n+ * then the connection keeps on. Without this flag, a failed client\n+ * authentication terminates the connection.\n+ *\n+ * Notes:\n+ *\n+ * - If the client's certificate can be validated and its public key is\n+ * supported, then a wrong signature value terminates the connection\n+ * regardless of that flag.\n+ *\n+ * - If using full-static ECDH, then a failure to validate the client's\n+ * certificate prevents the handshake from succeeding.\n+ */\n+#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 \u003c\u003c 2)\n+\n+/**\n * \u005cbrief Set the minimum and maximum supported protocol versions.\n *\n * The two provided versions MUST be supported by the implementation\n@@ -1158,6 +1198,44 @@ br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)\n }\n \n /**\n+ * \u005cbrief Set the RSA signature verification implementation.\n+ *\n+ * On the client, this is used to verify the server's signature on its\n+ * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server,\n+ * this is used to verify the client's CertificateVerify message (if a\n+ * client certificate is requested, and that certificate contains a RSA key).\n+ *\n+ * \u005cparam cc SSL engine context.\n+ * \u005cparam irsavrfy RSA signature verification implementation.\n+ */\n+static inline void\n+br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy)\n+{\n+\tcc-\u003eirsavrfy \u003d irsavrfy;\n+}\n+\n+/*\n+ * \u005cbrief Set the ECDSA implementation (signature verification).\n+ *\n+ * On the client, this is used to verify the server's signature on its\n+ * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server,\n+ * this is used to verify the client's CertificateVerify message (if a\n+ * client certificate is requested, that certificate contains an EC key,\n+ * and full-static ECDH is not used).\n+ *\n+ * The ECDSA implementation will use the EC core implementation configured\n+ * in the engine context.\n+ *\n+ * \u005cparam cc client context.\n+ * \u005cparam iecdsa ECDSA verification implementation.\n+ */\n+static inline void\n+br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa)\n+{\n+\tcc-\u003eiecdsa \u003d iecdsa;\n+}\n+\n+/**\n * \u005cbrief Set the I/O buffer for the SSL engine.\n *\n * Once this call has been made, `br_ssl_client_reset()` or\n@@ -1597,6 +1675,326 @@ void br_ssl_engine_close(br_ssl_engine_context *cc);\n */\n int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);\n \n+/*\n+ * Pre-declaration for the SSL client context.\n+ */\n+typedef struct br_ssl_client_context_ br_ssl_client_context;\n+\n+/**\n+ * \u005cbrief Type for the client certificate, if requested by the server.\n+ */\n+typedef struct {\n+\t/**\n+\t * \u005cbrief Authentication type.\n+\t *\n+\t * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA`\n+\t * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange).\n+\t */\n+\tint auth_type;\n+\n+\t/**\n+\t * \u005cbrief Hash function for computing the CertificateVerify.\n+\t *\n+\t * This is the symbolic identifier for the hash function that\n+\t * will be used to produce the hash of handshake messages, to\n+\t * be signed into the CertificateVerify. For full static ECDH\n+\t * (client and server certificates are both EC in the same\n+\t * curve, and static ECDH is used), this value is set to -1.\n+\t *\n+\t * Take care that with TLS 1.0 and 1.1, that value MUST match\n+\t * the protocol requirements: value must be 0 (MD5+SHA-1) for\n+\t * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only\n+\t * TLS 1.2 allows for other hash functions.\n+\t */\n+\tint hash_id;\n+\n+\t/**\n+\t * \u005cbrief Certificate chain to send to the server.\n+\t *\n+\t * This is an array of `br_x509_certificate` objects, each\n+\t * normally containing a DER-encoded certificate. The client\n+\t * code does not try to decode these elements. If there is no\n+\t * chain to send to the server, then this pointer shall be\n+\t * set to `NULL`.\n+\t */\n+\tconst br_x509_certificate *chain;\n+\n+\t/**\n+\t * \u005cbrief Certificate chain length (number of certificates).\n+\t *\n+\t * If there is no chain to send to the server, then this value\n+\t * shall be set to 0.\n+\t */\n+\tsize_t chain_len;\n+\n+} br_ssl_client_certificate;\n+\n+/*\n+ * Note: the constants below for signatures match the TLS constants.\n+ */\n+\n+/** \u005cbrief Client authentication type: static ECDH. */\n+#define BR_AUTH_ECDH 0\n+/** \u005cbrief Client authentication type: RSA signature. */\n+#define BR_AUTH_RSA 1\n+/** \u005cbrief Client authentication type: ECDSA signature. */\n+#define BR_AUTH_ECDSA 3\n+\n+/**\n+ * \u005cbrief Class type for a certificate handler (client side).\n+ *\n+ * A certificate handler selects a client certificate chain to send to\n+ * the server, upon explicit request from that server. It receives\n+ * the list of trust anchor DN from the server, and supported types\n+ * of certificates and signatures, and returns the chain to use. It\n+ * is also invoked to perform the corresponding private key operation\n+ * (a signature, or an ECDH computation).\n+ *\n+ * The SSL client engine will first push the trust anchor DN with\n+ * `start_name_list()`, `start_name()`, `append_name()`, `end_name()`\n+ * and `end_name_list()`. Then it will call `choose()`, to select the\n+ * actual chain (and signature/hash algorithms). Finally, it will call\n+ * either `do_sign()` or `do_keyx()`, depending on the algorithm choices.\n+ */\n+typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class;\n+struct br_ssl_client_certificate_class_ {\n+\t/**\n+\t * \u005cbrief Context size (in bytes).\n+\t */\n+\tsize_t context_size;\n+\n+\t/**\n+\t * \u005cbrief Begin reception of a list of trust anchor names. This\n+\t * is called while parsing the incoming CertificateRequest.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t */\n+\tvoid (*start_name_list)(const br_ssl_client_certificate_class **pctx);\n+\n+\t/**\n+\t * \u005cbrief Begin reception of a new trust anchor name.\n+\t *\n+\t * The total encoded name length is provided; it is less than\n+\t * 65535 bytes.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t * \u005cparam len encoded name length (in bytes).\n+\t */\n+\tvoid (*start_name)(const br_ssl_client_certificate_class **pctx,\n+\t\tsize_t len);\n+\n+\t/**\n+\t * \u005cbrief Receive some more bytes for the current trust anchor name.\n+\t *\n+\t * The provided reference (`data`) points to a transient buffer\n+\t * they may be reused as soon as this function returns. The chunk\n+\t * length (`len`) is never zero.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t * \u005cparam data anchor name chunk.\n+\t * \u005cparam len anchor name chunk length (in bytes).\n+\t */\n+\tvoid (*append_name)(const br_ssl_client_certificate_class **pctx,\n+\t\tconst unsigned char *data, size_t len);\n+\n+\t/**\n+\t * \u005cbrief End current trust anchor name.\n+\t *\n+\t * This function is called when all the encoded anchor name data\n+\t * has been provided.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t */\n+\tvoid (*end_name)(const br_ssl_client_certificate_class **pctx);\n+\n+\t/**\n+\t * \u005cbrief End list of trust anchor names.\n+\t *\n+\t * This function is called when all the anchor names in the\n+\t * CertificateRequest message have been obtained.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t */\n+\tvoid (*end_name_list)(const br_ssl_client_certificate_class **pctx);\n+\n+\t/**\n+\t * \u005cbrief Select client certificate and algorithms.\n+\t *\n+\t * This callback function shall fill the provided `choices`\n+\t * structure with the selected algorithms and certificate chain.\n+\t * The `hash_id`, `chain` and `chain_len` fields must be set. If\n+\t * the client cannot or does not wish to send a certificate,\n+\t * then it shall set `chain` to `NULL` and `chain_len` to 0.\n+\t *\n+\t * The `auth_types` parameter describes the authentication types,\n+\t * signature algorithms and hash functions that are supported by\n+\t * both the client context and the server, and compatible with\n+\t * the current protocol version. This is a bit field with the\n+\t * following contents:\n+\t *\n+\t * - If RSA signatures with hash function x are supported, then\n+\t * bit x is set.\n+\t *\n+\t * - If ECDSA signatures with hash function x are supported,\n+\t * then bit 8+x is set.\n+\t *\n+\t * - If static ECDH is supported, with a RSA-signed certificate,\n+\t * then bit 16 is set.\n+\t *\n+\t * - If static ECDH is supported, with an ECDSA-signed certificate,\n+\t * then bit 17 is set.\n+\t *\n+\t * Notes:\n+\t *\n+\t * - When using TLS 1.0 or 1.1, the hash function for RSA\n+\t * signatures is always the special MD5+SHA-1 (id 0), and the\n+\t * hash function for ECDSA signatures is always SHA-1 (id 2).\n+\t *\n+\t * - When using TLS 1.2, the list of hash functions is trimmed\n+\t * down to include only hash functions that the client context\n+\t * can support. The actual server list can be obtained with\n+\t * `br_ssl_client_get_server_hashes()`; that list may be used\n+\t * to select the certificate chain to send to the server.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t * \u005cparam cc SSL client context.\n+\t * \u005cparam auth_types supported authentication types and algorithms.\n+\t * \u005cparam choices destination structure for the policy choices.\n+\t */\n+\tvoid (*choose)(const br_ssl_client_certificate_class **pctx,\n+\t\tconst br_ssl_client_context *cc, uint32_t auth_types,\n+\t\tbr_ssl_client_certificate *choices);\n+\n+\t/**\n+\t * \u005cbrief Perform key exchange (client part).\n+\t *\n+\t * This callback is invoked in case of a full static ECDH key\n+\t * exchange:\n+\t *\n+\t * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`;\n+\t *\n+\t * - the server requests a client certificate;\n+\t *\n+\t * - the client has, and sends, a client certificate that\n+\t * uses an EC key in the same curve as the server's key,\n+\t * and chooses static ECDH (the `hash_id` field in the choice\n+\t * structure was set to -1).\n+\t *\n+\t * In that situation, this callback is invoked to compute the\n+\t * client-side ECDH: the provided `data` (of length `len` bytes)\n+\t * is the server's public key point (as decoded from its\n+\t * certificate), and the client shall multiply that point with\n+\t * its own private key, and write back the X coordinate of the\n+\t * resulting point in the same buffer, starting at offset 1\n+\t * (therefore, writing back the complete encoded point works).\n+\t *\n+\t * The callback must uphold the following:\n+\t *\n+\t * - If the input array does not have the proper length for\n+\t * an encoded curve point, then an error (0) shall be reported.\n+\t *\n+\t * - If the input array has the proper length, then processing\n+\t * MUST be constant-time, even if the data is not a valid\n+\t * encoded point.\n+\t *\n+\t * - This callback MUST check that the input point is valid.\n+\t *\n+\t * Returned value is 1 on success, 0 on error.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t * \u005cparam data server public key point.\n+\t * \u005cparam len server public key point length (in bytes).\n+\t * \u005creturn 1 on success, 0 on error.\n+\t */\n+\tuint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx,\n+\t\tunsigned char *data, size_t len);\n+\n+\t/**\n+\t * \u005cbrief Perform a signature (client authentication).\n+\t *\n+\t * This callback is invoked when a client certificate was sent,\n+\t * and static ECDH is not used. It shall compute a signature,\n+\t * using the client's private key, over the provided hash value\n+\t * (which is the hash of all previous handshake messages).\n+\t *\n+\t * On input, the hash value to sign is in `data`, of size\n+\t * `hv_len`; the involved hash function is identified by\n+\t * `hash_id`. The signature shall be computed and written\n+\t * back into `data`; the total size of that buffer is `len`\n+\t * bytes.\n+\t *\n+\t * This callback shall verify that the signature length does not\n+\t * exceed `len` bytes, and abstain from writing the signature if\n+\t * it does not fit.\n+\t *\n+\t * For RSA signatures, the `hash_id` may be 0, in which case\n+\t * this is the special header-less signature specified in TLS 1.0\n+\t * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1\n+\t * v1.5 signatures shall be computed.\n+\t *\n+\t * For ECDSA signatures, the signature value shall use the ASN.1\n+\t * based encoding.\n+\t *\n+\t * Returned value is the signature length (in bytes), or 0 on error.\n+\t *\n+\t * \u005cparam pctx certificate handler context.\n+\t * \u005cparam hash_id hash function identifier.\n+\t * \u005cparam hv_len hash value length (in bytes).\n+\t * \u005cparam data input/output buffer (hash value, then signature).\n+\t * \u005cparam len total buffer length (in bytes).\n+\t * \u005creturn signature length (in bytes) on success, or 0 on error.\n+\t */\n+\tsize_t (*do_sign)(const br_ssl_client_certificate_class **pctx,\n+\t\tint hash_id, size_t hv_len, unsigned char *data, size_t len);\n+};\n+\n+/**\n+ * \u005cbrief A single-chain RSA client certificate handler.\n+ *\n+ * This handler uses a single certificate chain, with a RSA\n+ * signature. The list of trust anchor DN is ignored.\n+ *\n+ * Apart from the first field (vtable pointer), its contents are\n+ * opaque and shall not be accessed directly.\n+ */\n+typedef struct {\n+\t/** \u005cbrief Pointer to vtable. */\n+\tconst br_ssl_client_certificate_class *vtable;\n+#ifndef BR_DOXYGEN_IGNORE\n+\tconst br_x509_certificate *chain;\n+\tsize_t chain_len;\n+\tconst br_rsa_private_key *sk;\n+\tbr_rsa_pkcs1_sign irsasign;\n+#endif\n+} br_ssl_client_certificate_rsa_context;\n+\n+/**\n+ * \u005cbrief A single-chain EC client certificate handler.\n+ *\n+ * This handler uses a single certificate chain, with a RSA\n+ * signature. The list of trust anchor DN is ignored.\n+ *\n+ * This handler may support both static ECDH, and ECDSA signatures\n+ * (either usage may be selectively disabled).\n+ *\n+ * Apart from the first field (vtable pointer), its contents are\n+ * opaque and shall not be accessed directly.\n+ */\n+typedef struct {\n+\t/** \u005cbrief Pointer to vtable. */\n+\tconst br_ssl_client_certificate_class *vtable;\n+#ifndef BR_DOXYGEN_IGNORE\n+\tconst br_x509_certificate *chain;\n+\tsize_t chain_len;\n+\tconst br_ec_private_key *sk;\n+\tunsigned allowed_usages;\n+\tunsigned issuer_key_type;\n+\tconst br_multihash_context *mhash;\n+\tconst br_ec_impl *iec;\n+\tbr_ecdsa_sign iecdsa;\n+#endif\n+} br_ssl_client_certificate_ec_context;\n+\n /**\n * \u005cbrief Context structure for a SSL client.\n *\n@@ -1605,7 +2003,7 @@ int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);\n * a pointer to that field. The other structure fields are opaque and\n * must not be accessed directly.\n */\n-typedef struct {\n+struct br_ssl_client_context_ {\n \t/**\n \t * \u005cbrief The encapsulated engine context.\n \t */\n@@ -1621,13 +2019,81 @@ typedef struct {\n \tuint16_t min_clienthello_len;\n \n \t/*\n+\t * Bit field for algoithms (hash + signature) supported by the\n+\t * server when requesting a client certificate.\n+\t */\n+\tuint16_t hashes;\n+\n+\t/*\n+\t * Server's public key curve.\n+\t */\n+\tint server_curve;\n+\n+\t/*\n+\t * Context for certificate handler.\n+\t */\n+\tconst br_ssl_client_certificate_class **client_auth_vtable;\n+\n+\t/*\n+\t * Client authentication type.\n+\t */\n+\tunsigned char auth_type;\n+\n+\t/*\n+\t * Hash function to use for the client signature. This is 0xFF\n+\t * if static ECDH is used.\n+\t */\n+\tunsigned char hash_id;\n+\n+\t/*\n+\t * For the core certificate handlers, thus avoiding (in most\n+\t * cases) the need for an externally provided policy context.\n+\t */\n+\tunion {\n+\t\tconst br_ssl_client_certificate_class *vtable;\n+\t\tbr_ssl_client_certificate_rsa_context single_rsa;\n+\t\tbr_ssl_client_certificate_ec_context single_ec;\n+\t} client_auth;\n+\n+\t/*\n \t * Implementations.\n \t */\n \tbr_rsa_public irsapub;\n-\tbr_rsa_pkcs1_vrfy irsavrfy;\n-\tbr_ecdsa_vrfy iecdsa;\n #endif\n-} br_ssl_client_context;\n+};\n+\n+/**\n+ * \u005cbrief Get the hash functions and signature algorithms supported by\n+ * the server.\n+ *\n+ * This is a field of bits: for hash function of ID x, bit x is set if\n+ * the hash function is supported in RSA signatures, 8+x if it is supported\n+ * with ECDSA. This information is conveyed by the server when requesting\n+ * a client certificate.\n+ *\n+ * \u005cparam cc client context.\n+ * \u005creturn the server-supported hash functions (for signatures).\n+ */\n+static inline uint16_t\n+br_ssl_client_get_server_hashes(const br_ssl_client_context *cc)\n+{\n+\treturn cc-\u003ehashes;\n+}\n+\n+/**\n+ * \u005cbrief Get the server key curve.\n+ *\n+ * This function returns the ID for the curve used by the server's public\n+ * key. This is set when the server's certificate chain is processed;\n+ * this value is 0 if the server's key is not an EC key.\n+ *\n+ * \u005creturn the server's public key curve ID, or 0.\n+ */\n+static inline int\n+br_ssl_client_get_server_curve(const br_ssl_client_context *cc)\n+{\n+\treturn cc-\u003eserver_curve;\n+}\n \n /*\n * Each br_ssl_client_init_xxx() function sets the list of supported\n@@ -1668,48 +2134,34 @@ void br_ssl_client_init_full(br_ssl_client_context *cc,\n void br_ssl_client_zero(br_ssl_client_context *cc);\n \n /**\n- * \u005cbrief Set the RSA public-key operations implementation.\n+ * \u005cbrief Set an externally provided client certificate handler context.\n *\n- * This will be used to encrypt the pre-master secret with the server's\n- * RSA public key (RSA-encryption cipher suites only).\n+ * The handler's methods are invoked when the server requests a client\n+ * certificate.\n *\n- * \u005cparam cc client context.\n- * \u005cparam irsapub RSA public-key encryption implementation.\n+ * \u005cparam cc client context.\n+ * \u005cparam pctx certificate handler context (pointer to its vtable field).\n */\n static inline void\n-br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)\n+br_ssl_client_set_client_certificate(br_ssl_client_context *cc,\n+\tconst br_ssl_client_certificate_class **pctx)\n {\n-\tcc-\u003eirsapub \u003d irsapub;\n+\tcc-\u003eclient_auth_vtable \u003d pctx;\n }\n \n /**\n- * \u005cbrief Set the RSA signature verification implementation.\n- *\n- * This will be used to verify the server's signature on its\n- * ServerKeyExchange message (ECDHE_RSA cipher suites only).\n- *\n- * \u005cparam cc client context.\n- * \u005cparam irsavrfy RSA signature verification implementation.\n- */\n-static inline void\n-br_ssl_client_set_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)\n-{\n-\tcc-\u003eirsavrfy \u003d irsavrfy;\n-}\n-\n-/*\n- * \u005cbrief Set the ECDSA implementation (signature verification).\n+ * \u005cbrief Set the RSA public-key operations implementation.\n *\n- * The ECDSA implementation will use the EC core implementation configured\n- * in the engine context.\n+ * This will be used to encrypt the pre-master secret with the server's\n+ * RSA public key (RSA-encryption cipher suites only).\n *\n- * \u005cparam cc client context.\n- * \u005cparam iecdsa ECDSA verification implementation.\n+ * \u005cparam cc client context.\n+ * \u005cparam irsapub RSA public-key encryption implementation.\n */\n static inline void\n-br_ssl_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)\n+br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)\n {\n-\tcc-\u003eiecdsa \u003d iecdsa;\n+\tcc-\u003eirsapub \u003d irsapub;\n }\n \n /**\n@@ -1784,6 +2236,73 @@ br_ssl_client_forget_session(br_ssl_client_context *cc)\n }\n \n /**\n+ * \u005cbrief Set client certificate chain and key (single RSA case).\n+ *\n+ * This function sets a client certificate chain, that the client will\n+ * send to the server whenever a client certificate is requested. This\n+ * certificate uses an RSA public key; the corresponding private key is\n+ * invoked for authentication. Trust anchor names sent by the server are\n+ * ignored.\n+ *\n+ * The provided chain and private key are linked in the client context;\n+ * they must remain valid as long as they may be used, i.e. normally\n+ * for the duration of the connection, since they might be invoked\n+ * again upon renegotiations.\n+ *\n+ * \u005cparam cc SSL client context.\n+ * \u005cparam chain client certificate chain (SSL order: EE comes first).\n+ * \u005cparam chain_len client chain length (number of certificates).\n+ * \u005cparam sk client private key.\n+ * \u005cparam irsasign RSA signature implementation (PKCS#1 v1.5).\n+ */\n+void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);\n+\n+/*\n+ * \u005cbrief Set the client certificate chain and key (single EC case).\n+ *\n+ * This function sets a client certificate chain, that the client will\n+ * send to the server whenever a client certificate is requested. This\n+ * certificate uses an EC public key; the corresponding private key is\n+ * invoked for authentication. Trust anchor names sent by the server are\n+ * ignored.\n+ *\n+ * The provided chain and private key are linked in the client context;\n+ * they must remain valid as long as they may be used, i.e. normally\n+ * for the duration of the connection, since they might be invoked\n+ * again upon renegotiations.\n+ *\n+ * The `allowed_usages` is a combination of usages, namely\n+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`\n+ * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value\n+ * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA\n+ * signature implementation must be provided; otherwise, the `iecdsa`\n+ * parameter may be 0.\n+ *\n+ * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or\n+ * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA\n+ * that issued (signed) the client certificate. That value is used with\n+ * full static ECDH: support of the certificate by the server depends\n+ * on how the certificate was signed. (Note: when using TLS 1.2, this\n+ * parameter is ignored; but its value matters for TLS 1.0 and 1.1.)\n+ *\n+ * \u005cparam cc server context.\n+ * \u005cparam chain server certificate chain to send.\n+ * \u005cparam chain_len chain length (number of certificates).\n+ * \u005cparam sk server private key (EC).\n+ * \u005cparam allowed_usages allowed private key usages.\n+ * \u005cparam cert_issuer_key_type issuing CA's key type.\n+ * \u005cparam iec EC core implementation.\n+ * \u005cparam iecdsa ECDSA signature implementation (\u0022asn1\u0022 format).\n+ */\n+void br_ssl_client_set_single_ec(br_ssl_client_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_ec_private_key *sk, unsigned allowed_usages,\n+\tunsigned cert_issuer_key_type,\n+\tconst br_ec_impl *iec, br_ecdsa_sign iecdsa);\n+\n+/**\n * \u005cbrief Type for a \u0022translated cipher suite\u0022, as an array of two\n * 16-bit integers.\n *\n@@ -1906,6 +2425,7 @@ typedef struct {\n \t * \u005cbrief Certificate chain length (number of certificates).\n \t */\n \tsize_t chain_len;\n+\n } br_ssl_server_choices;\n \n /**\n@@ -2244,10 +2764,6 @@ struct br_ssl_server_context_ {\n \t * Context for chain handler.\n \t */\n \tconst br_ssl_server_policy_class **policy_vtable;\n-\tconst br_x509_certificate *chain;\n-\tsize_t chain_len;\n-\tconst unsigned char *cert_cur;\n-\tsize_t cert_len;\n \tunsigned char sign_hash_id;\n \n \t/*\n@@ -2267,6 +2783,25 @@ struct br_ssl_server_context_ {\n \tsize_t ecdhe_key_len;\n \n \t/*\n+\t * Trust anchor names for client authentication. \u0022ta_names\u0022 and\n+\t * \u0022tas\u0022 cannot be both non-NULL.\n+\t */\n+\tconst br_x500_name *ta_names;\n+\tconst br_x509_trust_anchor *tas;\n+\tsize_t num_tas;\n+\tsize_t cur_dn_index;\n+\tconst unsigned char *cur_dn;\n+\tsize_t cur_dn_len;\n+\n+\t/*\n+\t * Buffer for the hash value computed over all handshake messages\n+\t * prior to CertificateVerify, and identifier for the hash function.\n+\t */\n+\tunsigned char hash_CV[64];\n+\tsize_t hash_CV_len;\n+\tint hash_CV_id;\n+\n+\t/*\n \t * Server-specific implementations.\n \t * (none for now)\n \t */\n@@ -2539,7 +3074,7 @@ void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,\n \tconst br_rsa_private_key *sk, unsigned allowed_usages,\n \tbr_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);\n \n-/*\n+/**\n * \u005cbrief Set the server certificate chain and key (single EC case).\n *\n * This function uses a policy context included in the server context.\n@@ -2570,6 +3105,61 @@ void br_ssl_server_set_single_ec(br_ssl_server_context *cc,\n \tconst br_ec_impl *iec, br_ecdsa_sign iecdsa);\n \n /**\n+ * \u005cbrief Activate client certificate authentication.\n+ *\n+ * The trust anchor encoded X.500 names (DN) to send to the client are\n+ * provided. A client certificate will be requested and validated through\n+ * the X.509 validator configured in the SSL engine. If `num` is 0, then\n+ * client certificate authentication is disabled.\n+ *\n+ * If the client does not send a certificate, or on validation failure,\n+ * the handshake aborts. Unauthenticated clients can be tolerated by\n+ * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag.\n+ *\n+ * The provided array is linked in, not copied, so that pointer must\n+ * remain valid as long as anchor names may be used.\n+ *\n+ * \u005cparam cc server context.\n+ * \u005cparam ta_names encoded trust anchor names.\n+ * \u005cparam num number of encoded trust anchor names.\n+ */\n+static inline void\n+br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc,\n+\tconst br_x500_name *ta_names, size_t num)\n+{\n+\tcc-\u003eta_names \u003d ta_names;\n+\tcc-\u003etas \u003d NULL;\n+\tcc-\u003enum_tas \u003d num;\n+}\n+\n+/**\n+ * \u005cbrief Activate client certificate authentication.\n+ *\n+ * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the\n+ * trust anchor names are provided not as an array of stand-alone names\n+ * (`br_x500_name` structures), but as an array of trust anchors\n+ * (`br_x509_trust_anchor` structures). The server engine itself will\n+ * only use the `dn` field of each trust anchor. This is meant to allow\n+ * defining a single array of trust anchors, to be used here and in the\n+ * X.509 validation engine itself.\n+ *\n+ * The provided array is linked in, not copied, so that pointer must\n+ * remain valid as long as anchor names may be used.\n+ *\n+ * \u005cparam cc server context.\n+ * \u005cparam tas trust anchors (only names are used).\n+ * \u005cparam num number of trust anchors.\n+ */\n+static inline void\n+br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc,\n+\tconst br_x509_trust_anchor *tas, size_t num)\n+{\n+\tcc-\u003eta_names \u003d NULL;\n+\tcc-\u003etas \u003d tas;\n+\tcc-\u003enum_tas \u003d num;\n+}\n+\n+/**\n * \u005cbrief Configure the cache for session parameters.\n *\n * The cache context is provided as a pointer to its first field (vtable\ndiff --git a/inc/bearssl_x509.h b/inc/bearssl_x509.h\nindex 84e73dc..c73b5b3 100644\n--- a/inc/bearssl_x509.h\n+++ b/inc/bearssl_x509.h\n@@ -95,12 +95,12 @@\n * include some limited processing for case-insensitive matching and\n * whitespace normalisation).\n *\n- * - When doing validation, a target public key type is provided. That\n- * type is the combination of a key algorithm (RSA or EC) and an\n- * intended key usage (key exchange or signature); in the context\n- * of a SSL/TLS client validating a server's certificate, the algorithm\n- * and usage are obtained from the cipher suite (e.g. ECDHE_RSA means\n- * that an RSA key for signatures is expected).\n+ * - Successful validation produces a public key type but also a set\n+ * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).\n+ * The caller is responsible for checking that the key type and\n+ * usages are compatible with the expected values (e.g. with the\n+ * selected cipher suite, when the client validates the server's\n+ * certificate).\n *\n * **Important caveats:**\n *\n@@ -234,13 +234,23 @@ typedef struct {\n } br_x509_pkey;\n \n /**\n+ * \u005cbrief Distinguished Name (X.500) structure.\n+ *\n+ * The DN is DER-encoded.\n+ */\n+typedef struct {\n+\t/** \u005cbrief Encoded DN data. */\n+\tunsigned char *data;\n+\t/** \u005cbrief Encoded DN length (in bytes). */\n+\tsize_t len;\n+} br_x500_name;\n+\n+/**\n * \u005cbrief Trust anchor structure.\n */\n typedef struct {\n \t/** \u005cbrief Encoded DN (X.500 name). */\n-\tunsigned char *dn;\n-\t/** \u005cbrief Encoded DN length (in bytes). */\n-\tsize_t dn_len;\n+\tbr_x500_name dn;\n \t/** \u005cbrief Anchor flags (e.g. `BR_X509_TA_CA`). */\n \tunsigned flags;\n \t/** \u005cbrief Anchor public key. */\n@@ -364,22 +374,16 @@ struct br_x509_class_ {\n \t * This method shall set the vtable (first field) of the context\n \t * structure.\n \t *\n-\t * The `expected_key_type` is a combination of the algorithm type\n-\t * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) and the key usage\n-\t * (`BR_KEYTYPE_KEYX` or `BR_KEYTYPE_SIGN`).\n-\t *\n \t * The `server_name`, if not `NULL`, will be considered as a\n \t * fully qualified domain name, to be matched against the `dNSName`\n \t * elements of the end-entity certificate's SAN extension (if there\n \t * is no SAN, then the Common Name from the subjectDN will be used).\n \t * If `server_name` is `NULL` then no such matching is performed.\n \t *\n-\t * \u005cparam ctx validation context.\n-\t * \u005cparam expected_key_type expected key type (algorithm and usage).\n-\t * \u005cparam server_name server name to match (or `NULL`).\n+\t * \u005cparam ctx validation context.\n+\t * \u005cparam server_name server name to match (or `NULL`).\n \t */\n \tvoid (*start_chain)(const br_x509_class **ctx,\n-\t\tunsigned expected_key_type,\n \t\tconst char *server_name);\n \n \t/**\n@@ -446,10 +450,17 @@ struct br_x509_class_ {\n \t * a decoded public key even if the chain did not end on a\n \t * trusted anchor.\n \t *\n+\t * If validation succeeded and `usage` is not `NULL`, then\n+\t * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`\n+\t * and/or `BR_KEYTYPE_KEYX` that specifies the validated key\n+\t * usage types. It is the caller's responsibility to check\n+\t * that value against the intended use of the public key.\n+\t *\n \t * \u005cparam ctx validation context.\n \t * \u005creturn the end-entity public key, or `NULL`.\n \t */\n-\tconst br_x509_pkey *(*get_pkey)(const br_x509_class *const *ctx);\n+\tconst br_x509_pkey *(*get_pkey)(\n+\t\tconst br_x509_class *const *ctx, unsigned *usages);\n };\n \n /**\n@@ -466,6 +477,7 @@ typedef struct {\n \tconst br_x509_class *vtable;\n #ifndef BR_DOXYGEN_IGNORE\n \tbr_x509_pkey pkey;\n+\tunsigned usages;\n #endif\n } br_x509_knownkey_context;\n \n@@ -477,26 +489,34 @@ extern const br_x509_class br_x509_knownkey_vtable;\n /**\n * \u005cbrief Initialize a \u0022known key\u0022 X.509 engine with a known RSA public key.\n *\n+ * The `usages` parameter indicates the allowed key usages for that key\n+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).\n+ *\n * The provided pointers are linked in, not copied, so they must remain\n * valid while the public key may be in usage.\n *\n- * \u005cparam ctx context to initialise.\n- * \u005cparam pk known public key.\n+ * \u005cparam ctx context to initialise.\n+ * \u005cparam pk known public key.\n+ * \u005cparam usages allowed key usages.\n */\n void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,\n-\tconst br_rsa_public_key *pk);\n+\tconst br_rsa_public_key *pk, unsigned usages);\n \n /**\n * \u005cbrief Initialize a \u0022known key\u0022 X.509 engine with a known EC public key.\n *\n+ * The `usages` parameter indicates the allowed key usages for that key\n+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).\n+ *\n * The provided pointers are linked in, not copied, so they must remain\n * valid while the public key may be in usage.\n *\n- * \u005cparam ctx context to initialise.\n- * \u005cparam pk known public key.\n+ * \u005cparam ctx context to initialise.\n+ * \u005cparam pk known public key.\n+ * \u005cparam usages allowed key usages.\n */\n void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,\n-\tconst br_ec_public_key *pk);\n+\tconst br_ec_public_key *pk, unsigned usages);\n \n #ifndef BR_DOXYGEN_IGNORE\n /*\n@@ -560,8 +580,8 @@ typedef struct {\n \t/* Server name to match with the SAN / CN of the EE certificate. */\n \tconst char *server_name;\n \n-\t/* Expected EE key type and usage. */\n-\tunsigned char expected_key_type;\n+\t/* Validated key usages. */\n+\tunsigned char key_usages;\n \n \t/* Explicitly set date and time. */\n \tuint32_t days, seconds;\ndiff --git a/src/ssl/ssl_ccert_single_ec.c b/src/ssl/ssl_ccert_single_ec.c\nnew file mode 100644\nindex 0000000..1df19a9\n--- /dev/null\n+++ b/src/ssl/ssl_ccert_single_ec.c\n@@ -0,0 +1,150 @@\n+/*\n+ * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining \n+ * a copy of this software and associated documentation files (the\n+ * \u0022Software\u0022), to deal in the Software without restriction, including\n+ * without limitation the rights to use, copy, modify, merge, publish,\n+ * distribute, sublicense, and/or sell copies of the Software, and to\n+ * permit persons to whom the Software is furnished to do so, subject to\n+ * the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be \n+ * included in all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+ * SOFTWARE.\n+ */\n+\n+#include \u0022inner.h\u0022\n+\n+static void\n+cc_none0(const br_ssl_client_certificate_class **pctx)\n+{\n+\t(void)pctx;\n+}\n+\n+static void\n+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)\n+{\n+\t(void)pctx;\n+\t(void)len;\n+}\n+\n+static void\n+cc_none2(const br_ssl_client_certificate_class **pctx,\n+\tconst unsigned char *data, size_t len)\n+{\n+\t(void)pctx;\n+\t(void)data;\n+\t(void)len;\n+}\n+\n+static void\n+cc_choose(const br_ssl_client_certificate_class **pctx,\n+\tconst br_ssl_client_context *cc, uint32_t auth_types,\n+\tbr_ssl_client_certificate *choices)\n+{\n+\tbr_ssl_client_certificate_ec_context *zc;\n+\tint x;\n+\tint scurve;\n+\n+\tzc \u003d (br_ssl_client_certificate_ec_context *)pctx;\n+\tscurve \u003d br_ssl_client_get_server_curve(cc);\n+\n+\tif ((zc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0\n+\t\t\u0026\u0026 scurve \u003d\u003d zc-\u003esk-\u003ecurve)\n+\t{\n+\t\tint x;\n+\n+\t\tx \u003d (zc-\u003eissuer_key_type \u003d\u003d BR_KEYTYPE_RSA) ? 16 : 17;\n+\t\tif (((auth_types \u003e\u003e x) \u0026 1) !\u003d 0) {\n+\t\t\tchoices-\u003eauth_type \u003d BR_AUTH_ECDH;\n+\t\t\tchoices-\u003ehash_id \u003d -1;\n+\t\t\tchoices-\u003echain \u003d zc-\u003echain;\n+\t\t\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * For ECDSA authentication, we must choose an appropriate\n+\t * hash function.\n+\t */\n+\tx \u003d br_ssl_choose_hash((unsigned)(auth_types \u003e\u003e 8));\n+\tif (x \u003d\u003d 0 || (zc-\u003eallowed_usages \u0026 BR_KEYTYPE_SIGN) \u003d\u003d 0) {\n+\t\tmemset(choices, 0, sizeof *choices);\n+\t\treturn;\n+\t}\n+\tchoices-\u003eauth_type \u003d BR_AUTH_ECDSA;\n+\tchoices-\u003ehash_id \u003d x;\n+\tchoices-\u003echain \u003d zc-\u003echain;\n+\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+}\n+\n+static uint32_t\n+cc_do_keyx(const br_ssl_client_certificate_class **pctx,\n+\tunsigned char *data, size_t len)\n+{\n+\tbr_ssl_client_certificate_ec_context *zc;\n+\n+\tzc \u003d (br_ssl_client_certificate_ec_context *)pctx;\n+\treturn zc-\u003eiec-\u003emul(data, len, zc-\u003esk-\u003ex, zc-\u003esk-\u003exlen, zc-\u003esk-\u003ecurve);\n+}\n+\n+static size_t\n+cc_do_sign(const br_ssl_client_certificate_class **pctx,\n+\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n+{\n+\tbr_ssl_client_certificate_ec_context *zc;\n+\tunsigned char hv[64];\n+\tconst br_hash_class *hc;\n+\n+\tzc \u003d (br_ssl_client_certificate_ec_context *)pctx;\n+\tmemcpy(hv, data, hv_len);\n+\thc \u003d br_multihash_getimpl(zc-\u003emhash, hash_id);\n+\tif (hc \u003d\u003d NULL) {\n+\t\treturn 0;\n+\t}\n+\tif (len \u003c 139) {\n+\t\treturn 0;\n+\t}\n+\treturn zc-\u003eiecdsa(zc-\u003eiec, hc, hv, zc-\u003esk, data);\n+}\n+\n+static const br_ssl_client_certificate_class ccert_vtable \u003d {\n+\tsizeof(br_ssl_client_certificate_ec_context),\n+\tcc_none0, /* start_name_list */\n+\tcc_none1, /* start_name */\n+\tcc_none2, /* append_name */\n+\tcc_none0, /* end_name */\n+\tcc_none0, /* end_name_list */\n+\tcc_choose,\n+\tcc_do_keyx,\n+\tcc_do_sign\n+};\n+\n+/* see bearssl_ssl.h */\n+void\n+br_ssl_client_set_single_ec(br_ssl_client_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_ec_private_key *sk, unsigned allowed_usages,\n+\tunsigned cert_issuer_key_type,\n+\tconst br_ec_impl *iec, br_ecdsa_sign iecdsa)\n+{\n+\tcc-\u003eclient_auth.single_ec.vtable \u003d \u0026ccert_vtable;\n+\tcc-\u003eclient_auth.single_ec.chain \u003d chain;\n+\tcc-\u003eclient_auth.single_ec.chain_len \u003d chain_len;\n+\tcc-\u003eclient_auth.single_ec.sk \u003d sk;\n+\tcc-\u003eclient_auth.single_ec.allowed_usages \u003d allowed_usages;\n+\tcc-\u003eclient_auth.single_ec.issuer_key_type \u003d cert_issuer_key_type;\n+\tcc-\u003eclient_auth.single_ec.mhash \u003d \u0026cc-\u003eeng.mhash;\n+\tcc-\u003eclient_auth.single_ec.iec \u003d iec;\n+\tcc-\u003eclient_auth.single_ec.iecdsa \u003d iecdsa;\n+\tcc-\u003eclient_auth_vtable \u003d \u0026cc-\u003eclient_auth.single_ec.vtable;\n+}\ndiff --git a/src/ssl/ssl_ccert_single_rsa.c b/src/ssl/ssl_ccert_single_rsa.c\nnew file mode 100644\nindex 0000000..690df20\n--- /dev/null\n+++ b/src/ssl/ssl_ccert_single_rsa.c\n@@ -0,0 +1,149 @@\n+/*\n+ * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining \n+ * a copy of this software and associated documentation files (the\n+ * \u0022Software\u0022), to deal in the Software without restriction, including\n+ * without limitation the rights to use, copy, modify, merge, publish,\n+ * distribute, sublicense, and/or sell copies of the Software, and to\n+ * permit persons to whom the Software is furnished to do so, subject to\n+ * the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be \n+ * included in all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+ * SOFTWARE.\n+ */\n+\n+#include \u0022inner.h\u0022\n+\n+static void\n+cc_none0(const br_ssl_client_certificate_class **pctx)\n+{\n+\t(void)pctx;\n+}\n+\n+static void\n+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)\n+{\n+\t(void)pctx;\n+\t(void)len;\n+}\n+\n+static void\n+cc_none2(const br_ssl_client_certificate_class **pctx,\n+\tconst unsigned char *data, size_t len)\n+{\n+\t(void)pctx;\n+\t(void)data;\n+\t(void)len;\n+}\n+\n+static void\n+cc_choose(const br_ssl_client_certificate_class **pctx,\n+\tconst br_ssl_client_context *cc, uint32_t auth_types,\n+\tbr_ssl_client_certificate *choices)\n+{\n+\tbr_ssl_client_certificate_rsa_context *zc;\n+\tint x;\n+\n+\t(void)cc;\n+\tzc \u003d (br_ssl_client_certificate_rsa_context *)pctx;\n+\tx \u003d br_ssl_choose_hash((unsigned)auth_types);\n+\tif (x \u003d\u003d 0 \u0026\u0026 (auth_types \u0026 1) \u003d\u003d 0) {\n+\t\tmemset(choices, 0, sizeof *choices);\n+\t}\n+\tchoices-\u003eauth_type \u003d BR_AUTH_RSA;\n+\tchoices-\u003ehash_id \u003d x;\n+\tchoices-\u003echain \u003d zc-\u003echain;\n+\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+}\n+\n+/*\n+ * OID for hash functions in RSA signatures.\n+ */\n+static const unsigned char HASH_OID_SHA1[] \u003d {\n+\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n+};\n+\n+static const unsigned char HASH_OID_SHA224[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n+};\n+\n+static const unsigned char HASH_OID_SHA256[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n+};\n+\n+static const unsigned char HASH_OID_SHA384[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n+};\n+\n+static const unsigned char HASH_OID_SHA512[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n+};\n+\n+static const unsigned char *HASH_OID[] \u003d {\n+\tHASH_OID_SHA1,\n+\tHASH_OID_SHA224,\n+\tHASH_OID_SHA256,\n+\tHASH_OID_SHA384,\n+\tHASH_OID_SHA512\n+};\n+\n+static size_t\n+cc_do_sign(const br_ssl_client_certificate_class **pctx,\n+\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n+{\n+\tbr_ssl_client_certificate_rsa_context *zc;\n+\tunsigned char hv[64];\n+\tconst unsigned char *hash_oid;\n+\tsize_t sig_len;\n+\n+\tzc \u003d (br_ssl_client_certificate_rsa_context *)pctx;\n+\tmemcpy(hv, data, hv_len);\n+\tif (hash_id \u003d\u003d 0) {\n+\t\thash_oid \u003d NULL;\n+\t} else if (hash_id \u003e\u003d 2 \u0026\u0026 hash_id \u003c\u003d 6) {\n+\t\thash_oid \u003d HASH_OID[hash_id - 2];\n+\t} else {\n+\t\treturn 0;\n+\t}\n+\tsig_len \u003d (zc-\u003esk-\u003en_bitlen + 7) \u003e\u003e 3;\n+\tif (len \u003c sig_len) {\n+\t\treturn 0;\n+\t}\n+\treturn zc-\u003eirsasign(hash_oid, hv, hv_len, zc-\u003esk, data) ? sig_len : 0;\n+}\n+\n+static const br_ssl_client_certificate_class ccert_vtable \u003d {\n+\tsizeof(br_ssl_client_certificate_rsa_context),\n+\tcc_none0, /* start_name_list */\n+\tcc_none1, /* start_name */\n+\tcc_none2, /* append_name */\n+\tcc_none0, /* end_name */\n+\tcc_none0, /* end_name_list */\n+\tcc_choose,\n+\t0,\n+\tcc_do_sign\n+};\n+\n+/* see bearssl_ssl.h */\n+void\n+br_ssl_client_set_single_rsa(br_ssl_client_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign)\n+{\n+\tcc-\u003eclient_auth.single_rsa.vtable \u003d \u0026ccert_vtable;\n+\tcc-\u003eclient_auth.single_rsa.chain \u003d chain;\n+\tcc-\u003eclient_auth.single_rsa.chain_len \u003d chain_len;\n+\tcc-\u003eclient_auth.single_rsa.sk \u003d sk;\n+\tcc-\u003eclient_auth.single_rsa.irsasign \u003d irsasign;\n+\tcc-\u003eclient_auth_vtable \u003d \u0026cc-\u003eclient_auth.single_rsa.vtable;\n+}\ndiff --git a/src/ssl/ssl_client_full.c b/src/ssl/ssl_client_full.c\nindex ad1f0cc..64f9327 100644\n--- a/src/ssl/ssl_client_full.c\n+++ b/src/ssl/ssl_client_full.c\n@@ -123,9 +123,9 @@ br_ssl_client_init_full(br_ssl_client_context *cc,\n \tbr_ssl_engine_set_suites(\u0026cc-\u003eeng, suites,\n \t\t(sizeof suites) / (sizeof suites[0]));\n \tbr_ssl_client_set_rsapub(cc, \u0026br_rsa_i31_public);\n-\tbr_ssl_client_set_rsavrfy(cc, \u0026br_rsa_i31_pkcs1_vrfy);\n+\tbr_ssl_engine_set_rsavrfy(\u0026cc-\u003eeng, \u0026br_rsa_i31_pkcs1_vrfy);\n \tbr_ssl_engine_set_ec(\u0026cc-\u003eeng, \u0026br_ec_prime_i31);\n-\tbr_ssl_client_set_ecdsa(cc, \u0026br_ecdsa_i31_vrfy_asn1);\n+\tbr_ssl_engine_set_ecdsa(\u0026cc-\u003eeng, \u0026br_ecdsa_i31_vrfy_asn1);\n \tbr_x509_minimal_set_rsa(xc, \u0026br_rsa_i31_pkcs1_vrfy);\n \tbr_x509_minimal_set_ecdsa(xc,\n \t\t\u0026br_ec_prime_i31, \u0026br_ecdsa_i31_vrfy_asn1);\ndiff --git a/src/ssl/ssl_hs_client.c b/src/ssl/ssl_hs_client.c\nindex a347cc6..e7334de 100644\n--- a/src/ssl/ssl_hs_client.c\n+++ b/src/ssl/ssl_hs_client.c\n@@ -110,7 +110,7 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)\n \tsize_t nlen, u;\n \n \txc \u003d ctx-\u003eeng.x509ctx;\n-\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \n \t/*\n \t * Compute actual RSA key length, in case there are leading zeros.\n@@ -200,9 +200,11 @@ static const unsigned char *HASH_OID[] \u003d {\n \n /*\n * Check the RSA signature on the ServerKeyExchange message.\n+ *\n * hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)\n * use_rsa non-zero for RSA signature, zero for ECDSA\n * sig_len signature length (in bytes); signature value is in the pad\n+ *\n * Returned value is 0 on success, or an error code.\n */\n static int\n@@ -216,7 +218,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n \tsize_t hv_len;\n \n \txc \u003d ctx-\u003eeng.x509ctx;\n-\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \tbr_multihash_zero(\u0026mhc);\n \tbr_multihash_copyimpl(\u0026mhc, \u0026ctx-\u003eeng.mhash);\n \tbr_multihash_init(\u0026mhc);\n@@ -253,14 +255,14 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n \t\t} else {\n \t\t\thash_oid \u003d NULL;\n \t\t}\n-\t\tif (!ctx-\u003eirsavrfy(ctx-\u003eeng.pad, sig_len,\n+\t\tif (!ctx-\u003eeng.irsavrfy(ctx-\u003eeng.pad, sig_len,\n \t\t\thash_oid, hv_len, \u0026pk-\u003ekey.rsa, tmp)\n \t\t\t|| memcmp(tmp, hv, hv_len) !\u003d 0)\n \t\t{\n \t\t\treturn BR_ERR_BAD_SIGNATURE;\n \t\t}\n \t} else {\n-\t\tif (!ctx-\u003eiecdsa(ctx-\u003eeng.iec, hv, hv_len, \u0026pk-\u003ekey.ec,\n+\t\tif (!ctx-\u003eeng.iecdsa(ctx-\u003eeng.iec, hv, hv_len, \u0026pk-\u003ekey.ec,\n \t\t\tctx-\u003eeng.pad, sig_len))\n \t\t{\n \t\t\treturn BR_ERR_BAD_SIGNATURE;\n@@ -270,7 +272,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n }\n \n /*\n- * Perform client-size ECDH (or ECDHE). The point that should be sent to\n+ * Perform client-side ECDH (or ECDHE). The point that should be sent to\n * the server is written in the pad; returned value is either the point\n * length (in bytes), or -x on error, with 'x' being an error code.\n *\n@@ -296,7 +298,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)\n \t\tconst br_x509_pkey *pk;\n \n \t\txc \u003d ctx-\u003eeng.x509ctx;\n-\t\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\t\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \t\tcurve \u003d pk-\u003ekey.ec.curve;\n \t\tpoint_src \u003d pk-\u003ekey.ec.q;\n \t\tpoint_len \u003d pk-\u003ekey.ec.qlen;\n@@ -347,6 +349,73 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)\n \treturn (int)glen;\n }\n \n+/*\n+ * Perform full static ECDH. This occurs only in the context of client\n+ * authentication with certificates: the server uses an EC public key,\n+ * the cipher suite is of type ECDH (not ECDHE), the server requested a\n+ * client certificate and accepts static ECDH, the client has a\n+ * certificate with an EC public key in the same curve, and accepts\n+ * static ECDH as well.\n+ *\n+ * Returned value is 0 on success, -1 on error.\n+ */\n+static int\n+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)\n+{\n+\tunsigned char point[133];\n+\tsize_t point_len;\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tpoint_len \u003d pk-\u003ekey.ec.qlen;\n+\tif (point_len \u003e sizeof point) {\n+\t\treturn -1;\n+\t}\n+\tmemcpy(point, pk-\u003ekey.ec.q, point_len);\n+\tif (!(*ctx-\u003eclient_auth_vtable)-\u003edo_keyx(\n+\t\tctx-\u003eclient_auth_vtable, point, point_len))\n+\t{\n+\t\treturn -1;\n+\t}\n+\tbr_ssl_engine_compute_master(\u0026ctx-\u003eeng,\n+\t\tprf_id, point + 1, point_len \u003e\u003e 1);\n+\treturn 0;\n+}\n+\n+/*\n+ * Compute the client-side signature. This is invoked only when a\n+ * signature-based client authentication was selected. The computed\n+ * signature is in the pad; its length (in bytes) is returned. On\n+ * error, 0 is returned.\n+ */\n+static size_t\n+make_client_sign(br_ssl_client_context *ctx)\n+{\n+\tsize_t hv_len;\n+\n+\t/*\n+\t * Compute hash of handshake messages so far. This \u0022cannot\u0022 fail\n+\t * because the list of supported hash functions provided to the\n+\t * client certificate handler was trimmed to include only the\n+\t * hash functions that the multi-hasher supports.\n+\t */\n+\tif (ctx-\u003ehash_id) {\n+\t\thv_len \u003d br_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tctx-\u003ehash_id, ctx-\u003eeng.pad);\n+\t} else {\n+\t\tbr_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tbr_md5_ID, ctx-\u003eeng.pad);\n+\t\tbr_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tbr_sha1_ID, ctx-\u003eeng.pad + 16);\n+\t\thv_len \u003d 36;\n+\t}\n+\treturn (*ctx-\u003eclient_auth_vtable)-\u003edo_sign(\n+\t\tctx-\u003eclient_auth_vtable, ctx-\u003ehash_id, hv_len,\n+\t\tctx-\u003eeng.pad, sizeof ctx-\u003eeng.pad);\n+}\n+\n \n \n static const uint8_t t0_datablock[] \u003d {\n@@ -366,10 +435,10 @@ static const uint8_t t0_datablock[] \u003d {\n };\n \n static const uint8_t t0_codeblock[] \u003d {\n-\t0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x01,\n-\t0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01, 0x01, 0x08,\n+\t0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01,\n+\t0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08,\n \t0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,\n-\t0x01, 0x02, 0x09, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01,\n+\t0x01, 0x02, 0x09, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01,\n@@ -387,9 +456,11 @@ static const uint8_t t0_codeblock[] \u003d {\n \tT0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01,\n+\tT0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,\n+\t0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00,\n \t0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)),\n \t0x00, 0x00, 0x01,\n@@ -400,6 +471,8 @@ static const uint8_t t0_codeblock[] \u003d {\n \tT0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00,\n \t0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00,\n+\t0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00,\n+\t0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),\n \t0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00,\n@@ -426,218 +499,259 @@ static const uint8_t t0_codeblock[] \u003d {\n \tT0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,\n \t0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),\n-\t0x00, 0x00, 0x09, 0x1B, 0x42, 0x06, 0x02, 0x52, 0x1C, 0x00, 0x00, 0x06,\n-\t0x08, 0x1E, 0x0D, 0x05, 0x02, 0x5B, 0x1C, 0x04, 0x01, 0x2D, 0x00, 0x00,\n-\t0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x7D, 0x1B, 0x48, 0x34, 0x81, 0x01,\n-\t0x1B, 0x05, 0x04, 0x4A, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0D, 0x06, 0x03,\n-\t0x81, 0x01, 0x00, 0x48, 0x04, 0x69, 0x00, 0x06, 0x02, 0x52, 0x1C, 0x00,\n-\t0x00, 0x1B, 0x6E, 0x34, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x34, 0x61, 0x1E,\n-\t0x81, 0x0F, 0x15, 0x6A, 0x01, 0x0C, 0x23, 0x00, 0x00, 0x1B, 0x16, 0x01,\n-\t0x08, 0x0B, 0x34, 0x46, 0x16, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00,\n-\t0x60, 0x2E, 0x1D, 0x13, 0x28, 0x06, 0x08, 0x02, 0x00, 0x81, 0x2E, 0x03,\n-\t0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x26, 0x02, 0x00, 0x1B, 0x13, 0x11,\n-\t0x06, 0x02, 0x59, 0x1C, 0x81, 0x2E, 0x04, 0x75, 0x01, 0x01, 0x00, 0x60,\n-\t0x2E, 0x01, 0x16, 0x6C, 0x2E, 0x26, 0x81, 0x32, 0x1D, 0x81, 0x16, 0x06,\n-\t0x0B, 0x01, 0x7F, 0x81, 0x12, 0x01, 0x7F, 0x81, 0x31, 0x04, 0x80, 0x42,\n-\t0x81, 0x13, 0x61, 0x1E, 0x81, 0x05, 0x01, T0_INT1(BR_KEYTYPE_SIGN),\n-\t0x11, 0x06, 0x02, 0x81, 0x17, 0x81, 0x1A, 0x1B, 0x01, 0x0D, 0x0D, 0x06,\n-\t0x09, 0x1A, 0x81, 0x19, 0x81, 0x1A, 0x01, 0x7F, 0x04, 0x02, 0x01, 0x00,\n-\t0x03, 0x00, 0x01, 0x0E, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x06, 0x02, 0x51,\n-\t0x1C, 0x25, 0x06, 0x02, 0x5C, 0x1C, 0x02, 0x00, 0x06, 0x02, 0x81, 0x38,\n-\t0x81, 0x33, 0x01, 0x7F, 0x81, 0x31, 0x01, 0x7F, 0x81, 0x12, 0x01, 0x01,\n-\t0x60, 0x2E, 0x01, 0x17, 0x6C, 0x2E, 0x00, 0x00, 0x2A, 0x2A, 0x00, 0x00,\n-\t0x7E, 0x01, 0x0C, 0x10, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,\n-\tT0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, 0x01, 0x01,\n-\t0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,\n+\t0x00, 0x00, 0x09, 0x25, 0x50, 0x06, 0x02, 0x60, 0x26, 0x00, 0x00, 0x06,\n+\t0x08, 0x2A, 0x0E, 0x05, 0x02, 0x69, 0x26, 0x04, 0x01, 0x3A, 0x00, 0x00,\n+\t0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x81, 0x0F, 0x25, 0x56, 0x41, 0x81,\n+\t0x13, 0x25, 0x05, 0x04, 0x58, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06,\n+\t0x03, 0x81, 0x13, 0x00, 0x56, 0x04, 0x69, 0x00, 0x06, 0x02, 0x60, 0x26,\n+\t0x00, 0x00, 0x25, 0x81, 0x00, 0x41, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x41,\n+\t0x71, 0x2A, 0x81, 0x21, 0x1C, 0x7C, 0x01, 0x0C, 0x2F, 0x00, 0x00, 0x25,\n+\t0x1E, 0x01, 0x08, 0x0B, 0x41, 0x54, 0x1E, 0x08, 0x00, 0x01, 0x03, 0x00,\n+\t0x01, 0x00, 0x6F, 0x3B, 0x27, 0x1A, 0x34, 0x06, 0x08, 0x02, 0x00, 0x81,\n+\t0x43, 0x03, 0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x3A, 0x02, 0x00, 0x25,\n+\t0x1A, 0x17, 0x06, 0x02, 0x67, 0x26, 0x81, 0x43, 0x04, 0x75, 0x01, 0x01,\n+\t0x00, 0x6F, 0x3B, 0x01, 0x16, 0x7E, 0x3B, 0x32, 0x81, 0x49, 0x27, 0x81,\n+\t0x29, 0x06, 0x0B, 0x01, 0x7F, 0x81, 0x24, 0x01, 0x7F, 0x81, 0x46, 0x04,\n+\t0x80, 0x62, 0x81, 0x26, 0x71, 0x2A, 0x81, 0x17, 0x01,\n+\tT0_INT1(BR_KEYTYPE_SIGN), 0x17, 0x06, 0x02, 0x81, 0x2A, 0x81, 0x2D,\n+\t0x25, 0x01, 0x0D, 0x0E, 0x06, 0x09, 0x24, 0x81, 0x2C, 0x81, 0x2D, 0x01,\n+\t0x7F, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01, 0x0E, 0x0E, 0x05, 0x02,\n+\t0x6A, 0x26, 0x06, 0x02, 0x5F, 0x26, 0x31, 0x06, 0x02, 0x6A, 0x26, 0x02,\n+\t0x00, 0x06, 0x22, 0x81, 0x47, 0x78, 0x2C, 0x01, 0x81, 0x7F, 0x0E, 0x06,\n+\t0x10, 0x24, 0x01, 0x10, 0x81, 0x52, 0x01, 0x00, 0x81, 0x51, 0x71, 0x2A,\n+\t0x81, 0x21, 0x23, 0x04, 0x06, 0x81, 0x4A, 0x06, 0x02, 0x81, 0x48, 0x04,\n+\t0x02, 0x81, 0x4A, 0x01, 0x7F, 0x81, 0x46, 0x01, 0x7F, 0x81, 0x24, 0x01,\n+\t0x01, 0x6F, 0x3B, 0x01, 0x17, 0x7E, 0x3B, 0x00, 0x00, 0x36, 0x36, 0x00,\n+\t0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x01, 0x00, 0x36, 0x0E, 0x06, 0x05,\n+\t0x24, 0x01, T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30,\n+\t0x01, 0x01, 0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,\n \tT0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02,\n-\t0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,\n+\t0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,\n \tT0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03,\n-\t0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,\n+\t0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,\n \tT0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04,\n-\t0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,\n+\t0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,\n \tT0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00,\n-\t0x34, 0x1A, 0x00, 0x00, 0x68, 0x20, 0x01, 0x0E, 0x0D, 0x06, 0x04, 0x01,\n-\t0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x30, 0x06, 0x04, 0x01, 0x06,\n-\t0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x6D, 0x20, 0x1B, 0x06, 0x08, 0x01,\n-\t0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x1A, 0x01, 0x05, 0x00, 0x01,\n-\t0x31, 0x03, 0x00, 0x1A, 0x01, 0x00, 0x33, 0x06, 0x03, 0x02, 0x00, 0x08,\n-\t0x32, 0x06, 0x03, 0x02, 0x00, 0x08, 0x1B, 0x06, 0x06, 0x01, 0x01, 0x0B,\n-\t0x01, 0x06, 0x08, 0x00, 0x00, 0x6F, 0x2F, 0x1B, 0x06, 0x03, 0x01, 0x09,\n-\t0x08, 0x00, 0x01, 0x30, 0x1B, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x1B,\n-\t0x06, 0x0E, 0x1B, 0x01, 0x01, 0x11, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01,\n-\t0x01, 0x10, 0x04, 0x6F, 0x1A, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06,\n-\t0x08, 0x00, 0x00, 0x67, 0x1F, 0x34, 0x10, 0x01, 0x01, 0x11, 0x27, 0x00,\n-\t0x00, 0x81, 0x03, 0x81, 0x2D, 0x1B, 0x01, 0x07, 0x11, 0x01, 0x00, 0x2A,\n-\t0x0D, 0x06, 0x0A, 0x1A, 0x01, 0x10, 0x11, 0x06, 0x02, 0x81, 0x03, 0x04,\n-\t0x32, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x29, 0x1A, 0x1A, 0x01, 0x00, 0x60,\n-\t0x2E, 0x81, 0x15, 0x6D, 0x20, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x81, 0x0C,\n-\t0x29, 0x06, 0x11, 0x1D, 0x13, 0x28, 0x06, 0x05, 0x81, 0x2D, 0x1A, 0x04,\n-\t0x77, 0x01, 0x80, 0x64, 0x81, 0x26, 0x04, 0x02, 0x81, 0x03, 0x04, 0x03,\n-\t0x5C, 0x1C, 0x1A, 0x04, 0xFF, 0x35, 0x01, 0x1B, 0x03, 0x00, 0x09, 0x1B,\n-\t0x42, 0x06, 0x02, 0x52, 0x1C, 0x02, 0x00, 0x00, 0x00, 0x7E, 0x01, 0x0F,\n-\t0x11, 0x00, 0x00, 0x5F, 0x20, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x10, 0x1A,\n-\t0x1B, 0x01, 0x01, 0x0C, 0x06, 0x03, 0x1A, 0x01, 0x02, 0x5F, 0x2E, 0x01,\n-\t0x00, 0x04, 0x22, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x15, 0x1A, 0x01, 0x00,\n-\t0x5F, 0x2E, 0x1B, 0x01, 0x80, 0x64, 0x0D, 0x06, 0x05, 0x01, 0x82, 0x00,\n-\t0x08, 0x1C, 0x44, 0x00, 0x04, 0x07, 0x1A, 0x01, 0x82, 0x00, 0x08, 0x1C,\n-\t0x1A, 0x00, 0x00, 0x01, 0x00, 0x21, 0x06, 0x06, 0x2C, 0x81, 0x10, 0x29,\n-\t0x04, 0x77, 0x1B, 0x06, 0x04, 0x01, 0x01, 0x73, 0x2E, 0x00, 0x00, 0x21,\n-\t0x06, 0x0B, 0x6B, 0x20, 0x01, 0x14, 0x0C, 0x06, 0x02, 0x5C, 0x1C, 0x04,\n-\t0x12, 0x81, 0x2D, 0x01, 0x07, 0x11, 0x1B, 0x01, 0x02, 0x0C, 0x06, 0x06,\n-\t0x06, 0x02, 0x5C, 0x1C, 0x04, 0x6F, 0x1A, 0x81, 0x23, 0x01, 0x01, 0x0C,\n-\t0x25, 0x29, 0x06, 0x02, 0x4B, 0x1C, 0x1B, 0x01, 0x01, 0x81, 0x29, 0x28,\n-\t0x81, 0x14, 0x00, 0x01, 0x81, 0x1A, 0x01, 0x0B, 0x0D, 0x05, 0x02, 0x5C,\n-\t0x1C, 0x61, 0x1E, 0x81, 0x05, 0x41, 0x81, 0x21, 0x81, 0x0E, 0x1B, 0x06,\n-\t0x26, 0x81, 0x21, 0x81, 0x0E, 0x1B, 0x40, 0x1B, 0x06, 0x19, 0x1B, 0x01,\n-\t0x82, 0x00, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x1B, 0x03,\n-\t0x00, 0x6A, 0x02, 0x00, 0x81, 0x18, 0x02, 0x00, 0x3D, 0x04, 0x64, 0x7F,\n-\t0x3E, 0x04, 0x57, 0x7F, 0x7F, 0x3F, 0x1B, 0x06, 0x01, 0x1C, 0x1A, 0x00,\n-\t0x00, 0x81, 0x00, 0x81, 0x1A, 0x01, 0x14, 0x0C, 0x06, 0x02, 0x5C, 0x1C,\n-\t0x6A, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x18, 0x7F, 0x6A, 0x1B, 0x01,\n-\t0x0C, 0x08, 0x01, 0x0C, 0x22, 0x05, 0x02, 0x4E, 0x1C, 0x00, 0x00, 0x81,\n-\t0x1B, 0x06, 0x02, 0x5C, 0x1C, 0x06, 0x02, 0x50, 0x1C, 0x00, 0x09, 0x81,\n-\t0x1A, 0x01, 0x02, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x81, 0x20, 0x03, 0x00,\n-\t0x02, 0x00, 0x79, 0x1E, 0x0A, 0x02, 0x00, 0x78, 0x1E, 0x0E, 0x29, 0x06,\n-\t0x02, 0x5D, 0x1C, 0x02, 0x00, 0x77, 0x1E, 0x0C, 0x06, 0x02, 0x55, 0x1C,\n-\t0x02, 0x00, 0x7A, 0x2D, 0x70, 0x01, 0x20, 0x81, 0x18, 0x01, 0x00, 0x03,\n-\t0x01, 0x81, 0x22, 0x03, 0x02, 0x02, 0x02, 0x01, 0x20, 0x0E, 0x06, 0x02,\n-\t0x5A, 0x1C, 0x6A, 0x02, 0x02, 0x81, 0x18, 0x02, 0x02, 0x72, 0x20, 0x0D,\n-\t0x02, 0x02, 0x01, 0x00, 0x0E, 0x11, 0x06, 0x0B, 0x71, 0x6A, 0x02, 0x02,\n-\t0x22, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x01, 0x71, 0x6A, 0x02, 0x02, 0x23,\n-\t0x02, 0x02, 0x72, 0x2E, 0x02, 0x00, 0x76, 0x02, 0x01, 0x7C, 0x81, 0x20,\n-\t0x1B, 0x81, 0x24, 0x42, 0x06, 0x02, 0x4C, 0x1C, 0x61, 0x02, 0x01, 0x7C,\n-\t0x81, 0x22, 0x06, 0x02, 0x4D, 0x1C, 0x1B, 0x06, 0x81, 0x3D, 0x81, 0x20,\n-\t0x81, 0x0E, 0x81, 0x0A, 0x03, 0x03, 0x81, 0x08, 0x03, 0x04, 0x81, 0x06,\n-\t0x03, 0x05, 0x81, 0x09, 0x03, 0x06, 0x81, 0x0B, 0x03, 0x07, 0x81, 0x07,\n-\t0x03, 0x08, 0x1B, 0x06, 0x81, 0x0B, 0x81, 0x20, 0x01, 0x00, 0x2A, 0x0D,\n-\t0x06, 0x10, 0x1A, 0x02, 0x03, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03,\n-\t0x03, 0x81, 0x1F, 0x04, 0x80, 0x70, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x10,\n-\t0x1A, 0x02, 0x05, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x05, 0x81,\n-\t0x1D, 0x04, 0x80, 0x5A, 0x01, 0x83, 0xFE, 0x01, 0x2A, 0x0D, 0x06, 0x10,\n-\t0x1A, 0x02, 0x04, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x04, 0x81,\n-\t0x1E, 0x04, 0x80, 0x42, 0x01, 0x0D, 0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02,\n-\t0x06, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x06, 0x81, 0x1C, 0x04,\n-\t0x2D, 0x01, 0x0A, 0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02, 0x07, 0x05, 0x02,\n-\t0x56, 0x1C, 0x01, 0x00, 0x03, 0x07, 0x81, 0x1C, 0x04, 0x18, 0x01, 0x0B,\n-\t0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02, 0x08, 0x05, 0x02, 0x56, 0x1C, 0x01,\n-\t0x00, 0x03, 0x08, 0x81, 0x1C, 0x04, 0x03, 0x56, 0x1C, 0x1A, 0x04, 0xFE,\n-\t0x71, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0E, 0x06, 0x02,\n-\t0x53, 0x1C, 0x01, 0x01, 0x6D, 0x2E, 0x7F, 0x7F, 0x02, 0x01, 0x00, 0x04,\n-\t0x81, 0x1A, 0x01, 0x0C, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x81, 0x22, 0x01,\n-\t0x03, 0x0D, 0x05, 0x02, 0x57, 0x1C, 0x81, 0x20, 0x1B, 0x64, 0x2E, 0x1B,\n-\t0x01, 0x20, 0x0F, 0x06, 0x02, 0x57, 0x1C, 0x30, 0x34, 0x10, 0x01, 0x01,\n-\t0x11, 0x05, 0x02, 0x57, 0x1C, 0x81, 0x22, 0x1B, 0x01, 0x81, 0x05, 0x0E,\n-\t0x06, 0x02, 0x57, 0x1C, 0x1B, 0x66, 0x2E, 0x65, 0x34, 0x81, 0x18, 0x76,\n-\t0x1E, 0x01, 0x86, 0x03, 0x0F, 0x03, 0x00, 0x61, 0x1E, 0x81, 0x2B, 0x03,\n-\t0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x00, 0x06, 0x23, 0x81, 0x22, 0x1B,\n-\t0x1B, 0x01, 0x02, 0x0A, 0x34, 0x01, 0x06, 0x0E, 0x29, 0x06, 0x02, 0x57,\n-\t0x1C, 0x03, 0x02, 0x81, 0x22, 0x02, 0x01, 0x01, 0x01, 0x0B, 0x01, 0x03,\n-\t0x08, 0x0D, 0x05, 0x02, 0x57, 0x1C, 0x04, 0x08, 0x02, 0x01, 0x06, 0x04,\n-\t0x01, 0x00, 0x03, 0x02, 0x81, 0x20, 0x1B, 0x03, 0x03, 0x1B, 0x01, 0x84,\n-\t0x00, 0x0E, 0x06, 0x02, 0x58, 0x1C, 0x6A, 0x34, 0x81, 0x18, 0x02, 0x02,\n-\t0x02, 0x01, 0x02, 0x03, 0x3A, 0x1B, 0x06, 0x01, 0x1C, 0x1A, 0x7F, 0x00,\n-\t0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x7B, 0x02, 0x01, 0x02, 0x00,\n-\t0x2B, 0x1B, 0x01, 0x00, 0x0D, 0x06, 0x02, 0x4A, 0x00, 0x81, 0x2F, 0x04,\n-\t0x73, 0x00, 0x1B, 0x06, 0x05, 0x81, 0x22, 0x1A, 0x04, 0x78, 0x1A, 0x00,\n-\t0x00, 0x81, 0x1B, 0x1B, 0x44, 0x06, 0x07, 0x1A, 0x06, 0x02, 0x50, 0x1C,\n-\t0x04, 0x73, 0x00, 0x00, 0x81, 0x23, 0x01, 0x03, 0x81, 0x21, 0x34, 0x1A,\n-\t0x34, 0x00, 0x00, 0x81, 0x20, 0x81, 0x27, 0x00, 0x00, 0x81, 0x20, 0x01,\n-\t0x01, 0x0D, 0x05, 0x02, 0x4F, 0x1C, 0x81, 0x22, 0x01, 0x08, 0x08, 0x68,\n-\t0x20, 0x0D, 0x05, 0x02, 0x4F, 0x1C, 0x00, 0x00, 0x81, 0x20, 0x6D, 0x20,\n-\t0x05, 0x16, 0x01, 0x01, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x81, 0x22, 0x01,\n-\t0x00, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x01, 0x02, 0x6D, 0x2E, 0x04, 0x1E,\n-\t0x01, 0x19, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x81, 0x22, 0x01, 0x18, 0x0D,\n-\t0x05, 0x02, 0x53, 0x1C, 0x6A, 0x01, 0x18, 0x81, 0x18, 0x6E, 0x6A, 0x01,\n-\t0x18, 0x22, 0x05, 0x02, 0x53, 0x1C, 0x00, 0x00, 0x81, 0x20, 0x06, 0x02,\n-\t0x54, 0x1C, 0x00, 0x00, 0x01, 0x02, 0x7B, 0x81, 0x23, 0x01, 0x08, 0x0B,\n-\t0x81, 0x23, 0x08, 0x00, 0x00, 0x01, 0x03, 0x7B, 0x81, 0x23, 0x01, 0x08,\n-\t0x0B, 0x81, 0x23, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x23, 0x08, 0x00, 0x00,\n-\t0x01, 0x01, 0x7B, 0x81, 0x23, 0x00, 0x00, 0x2C, 0x1B, 0x42, 0x05, 0x01,\n-\t0x00, 0x1A, 0x81, 0x2F, 0x04, 0x75, 0x02, 0x03, 0x00, 0x75, 0x20, 0x03,\n-\t0x01, 0x01, 0x00, 0x1B, 0x02, 0x01, 0x0A, 0x06, 0x10, 0x1B, 0x01, 0x01,\n-\t0x0B, 0x74, 0x08, 0x1E, 0x02, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x46, 0x04,\n-\t0x6A, 0x1A, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x15, 0x6C, 0x2E, 0x34, 0x3C,\n-\t0x1A, 0x3C, 0x1A, 0x1D, 0x00, 0x00, 0x01, 0x01, 0x34, 0x81, 0x25, 0x00,\n-\t0x00, 0x34, 0x2A, 0x7B, 0x34, 0x1B, 0x06, 0x06, 0x81, 0x23, 0x1A, 0x47,\n-\t0x04, 0x77, 0x1A, 0x00, 0x00, 0x1B, 0x01, 0x81, 0xAC, 0x00, 0x0D, 0x06,\n-\t0x04, 0x1A, 0x01, 0x7F, 0x00, 0x7E, 0x43, 0x00, 0x02, 0x03, 0x00, 0x61,\n-\t0x1E, 0x7E, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x11, 0x02, 0x01, 0x01,\n-\t0x04, 0x10, 0x01, 0x0F, 0x11, 0x02, 0x01, 0x01, 0x08, 0x10, 0x01, 0x0F,\n-\t0x11, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x10, 0x1A, 0x01, 0x00, 0x01, 0x18,\n-\t0x02, 0x00, 0x06, 0x03, 0x37, 0x04, 0x01, 0x38, 0x04, 0x80, 0x56, 0x01,\n-\t0x01, 0x2A, 0x0D, 0x06, 0x10, 0x1A, 0x01, 0x01, 0x01, 0x10, 0x02, 0x00,\n-\t0x06, 0x03, 0x37, 0x04, 0x01, 0x38, 0x04, 0x80, 0x40, 0x01, 0x02, 0x2A,\n-\t0x0D, 0x06, 0x0F, 0x1A, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03,\n-\t0x37, 0x04, 0x01, 0x38, 0x04, 0x2B, 0x01, 0x03, 0x2A, 0x0D, 0x06, 0x0E,\n-\t0x1A, 0x1A, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x35, 0x04, 0x01, 0x36,\n-\t0x04, 0x17, 0x01, 0x04, 0x2A, 0x0D, 0x06, 0x0E, 0x1A, 0x1A, 0x01, 0x20,\n-\t0x02, 0x00, 0x06, 0x03, 0x35, 0x04, 0x01, 0x36, 0x04, 0x03, 0x52, 0x1C,\n-\t0x1A, 0x00, 0x00, 0x7E, 0x01, 0x0C, 0x10, 0x1B, 0x45, 0x34, 0x01, 0x03,\n-\t0x0A, 0x11, 0x00, 0x00, 0x7E, 0x01, 0x0C, 0x10, 0x01, 0x01, 0x0D, 0x00,\n-\t0x00, 0x7E, 0x01, 0x0C, 0x10, 0x44, 0x00, 0x00, 0x14, 0x01, 0x00, 0x5E,\n-\t0x20, 0x1B, 0x06, 0x20, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x07, 0x1A, 0x01,\n-\t0x00, 0x81, 0x02, 0x04, 0x11, 0x01, 0x02, 0x2A, 0x0D, 0x06, 0x0A, 0x1A,\n-\t0x60, 0x20, 0x06, 0x03, 0x01, 0x10, 0x29, 0x04, 0x01, 0x1A, 0x04, 0x01,\n-\t0x1A, 0x63, 0x20, 0x05, 0x35, 0x21, 0x06, 0x32, 0x6B, 0x20, 0x01, 0x14,\n-\t0x2A, 0x0D, 0x06, 0x06, 0x1A, 0x01, 0x02, 0x29, 0x04, 0x24, 0x01, 0x15,\n-\t0x2A, 0x0D, 0x06, 0x0B, 0x1A, 0x81, 0x11, 0x06, 0x04, 0x01, 0x7F, 0x81,\n-\t0x02, 0x04, 0x13, 0x01, 0x16, 0x2A, 0x0D, 0x06, 0x06, 0x1A, 0x01, 0x01,\n-\t0x29, 0x04, 0x07, 0x1A, 0x01, 0x04, 0x29, 0x01, 0x00, 0x1A, 0x13, 0x06,\n-\t0x03, 0x01, 0x08, 0x29, 0x00, 0x00, 0x14, 0x1B, 0x05, 0x10, 0x21, 0x06,\n-\t0x0D, 0x6B, 0x20, 0x01, 0x15, 0x0D, 0x06, 0x05, 0x1A, 0x81, 0x11, 0x04,\n-\t0x01, 0x17, 0x00, 0x00, 0x81, 0x2D, 0x01, 0x07, 0x11, 0x01, 0x01, 0x0E,\n-\t0x06, 0x02, 0x5C, 0x1C, 0x00, 0x01, 0x03, 0x00, 0x1D, 0x13, 0x06, 0x05,\n-\t0x02, 0x00, 0x6C, 0x2E, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x73, 0x00, 0x01,\n-\t0x14, 0x81, 0x30, 0x01, 0x01, 0x81, 0x3C, 0x1D, 0x1B, 0x01, 0x00, 0x81,\n-\t0x29, 0x01, 0x16, 0x81, 0x30, 0x81, 0x34, 0x1D, 0x00, 0x02, 0x81, 0x08,\n-\t0x81, 0x0A, 0x08, 0x81, 0x06, 0x08, 0x81, 0x09, 0x08, 0x81, 0x0B, 0x08,\n-\t0x81, 0x07, 0x08, 0x03, 0x00, 0x01, 0x01, 0x81, 0x3C, 0x01, 0x27, 0x72,\n-\t0x20, 0x08, 0x75, 0x20, 0x01, 0x01, 0x0B, 0x08, 0x02, 0x00, 0x06, 0x04,\n-\t0x48, 0x02, 0x00, 0x08, 0x69, 0x1E, 0x2A, 0x09, 0x1B, 0x45, 0x06, 0x24,\n-\t0x02, 0x00, 0x05, 0x04, 0x34, 0x48, 0x34, 0x49, 0x01, 0x04, 0x09, 0x1B,\n-\t0x42, 0x06, 0x03, 0x1A, 0x01, 0x00, 0x1B, 0x01, 0x04, 0x08, 0x02, 0x00,\n-\t0x08, 0x03, 0x00, 0x34, 0x01, 0x04, 0x08, 0x2A, 0x08, 0x34, 0x04, 0x03,\n-\t0x1A, 0x01, 0x7F, 0x03, 0x01, 0x81, 0x3B, 0x78, 0x1E, 0x81, 0x3A, 0x62,\n-\t0x01, 0x04, 0x12, 0x62, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x24, 0x62, 0x01,\n-\t0x20, 0x81, 0x35, 0x71, 0x72, 0x20, 0x81, 0x37, 0x75, 0x20, 0x1B, 0x01,\n-\t0x01, 0x0B, 0x81, 0x3A, 0x74, 0x34, 0x1B, 0x06, 0x11, 0x47, 0x2A, 0x1E,\n-\t0x1B, 0x81, 0x28, 0x05, 0x02, 0x4C, 0x1C, 0x81, 0x3A, 0x34, 0x48, 0x34,\n-\t0x04, 0x6C, 0x4A, 0x01, 0x01, 0x81, 0x3C, 0x01, 0x00, 0x81, 0x3C, 0x02,\n-\t0x00, 0x06, 0x81, 0x47, 0x02, 0x00, 0x81, 0x3A, 0x81, 0x08, 0x06, 0x12,\n-\t0x01, 0x83, 0xFE, 0x01, 0x81, 0x3A, 0x6E, 0x81, 0x08, 0x01, 0x04, 0x09,\n-\t0x1B, 0x81, 0x3A, 0x47, 0x81, 0x37, 0x81, 0x0A, 0x06, 0x1C, 0x01, 0x00,\n-\t0x81, 0x3A, 0x6F, 0x81, 0x0A, 0x01, 0x04, 0x09, 0x1B, 0x81, 0x3A, 0x01,\n-\t0x02, 0x09, 0x1B, 0x81, 0x3A, 0x01, 0x00, 0x81, 0x3C, 0x01, 0x03, 0x09,\n-\t0x81, 0x36, 0x81, 0x06, 0x06, 0x0F, 0x01, 0x01, 0x81, 0x3A, 0x01, 0x01,\n-\t0x81, 0x3A, 0x68, 0x20, 0x01, 0x08, 0x09, 0x81, 0x3C, 0x81, 0x09, 0x06,\n-\t0x1F, 0x01, 0x0D, 0x81, 0x3A, 0x81, 0x09, 0x01, 0x04, 0x09, 0x1B, 0x81,\n-\t0x3A, 0x01, 0x02, 0x09, 0x81, 0x3A, 0x32, 0x06, 0x04, 0x01, 0x03, 0x81,\n-\t0x39, 0x33, 0x06, 0x04, 0x01, 0x01, 0x81, 0x39, 0x81, 0x0B, 0x1B, 0x06,\n-\t0x27, 0x01, 0x0A, 0x81, 0x3A, 0x01, 0x04, 0x09, 0x1B, 0x81, 0x3A, 0x49,\n-\t0x81, 0x3A, 0x30, 0x01, 0x00, 0x1B, 0x01, 0x20, 0x0A, 0x06, 0x0E, 0x81,\n-\t0x04, 0x10, 0x01, 0x01, 0x11, 0x06, 0x03, 0x1B, 0x81, 0x3A, 0x46, 0x04,\n-\t0x6C, 0x4A, 0x04, 0x01, 0x1A, 0x81, 0x07, 0x06, 0x0D, 0x01, 0x0B, 0x81,\n-\t0x3A, 0x01, 0x02, 0x81, 0x3A, 0x01, 0x82, 0x00, 0x81, 0x3A, 0x02, 0x01,\n-\t0x42, 0x05, 0x14, 0x01, 0x15, 0x81, 0x3A, 0x02, 0x01, 0x1B, 0x81, 0x3A,\n-\t0x1B, 0x06, 0x07, 0x47, 0x01, 0x00, 0x81, 0x3C, 0x04, 0x76, 0x1A, 0x00,\n-\t0x00, 0x01, 0x10, 0x81, 0x3C, 0x61, 0x1E, 0x1B, 0x81, 0x2C, 0x06, 0x10,\n-\t0x81, 0x0F, 0x19, 0x1B, 0x48, 0x81, 0x3B, 0x1B, 0x81, 0x3A, 0x6A, 0x34,\n-\t0x81, 0x35, 0x04, 0x12, 0x1B, 0x81, 0x2A, 0x34, 0x81, 0x0F, 0x18, 0x1B,\n-\t0x46, 0x81, 0x3B, 0x1B, 0x81, 0x3C, 0x6A, 0x34, 0x81, 0x35, 0x00, 0x00,\n-\t0x81, 0x00, 0x01, 0x14, 0x81, 0x3C, 0x01, 0x0C, 0x81, 0x3B, 0x6A, 0x01,\n-\t0x0C, 0x81, 0x35, 0x00, 0x00, 0x3B, 0x1B, 0x01, 0x00, 0x0D, 0x06, 0x02,\n-\t0x4A, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x72, 0x00, 0x1B, 0x81, 0x3A, 0x81,\n-\t0x35, 0x00, 0x00, 0x1B, 0x81, 0x3C, 0x81, 0x35, 0x00, 0x00, 0x01, 0x0B,\n-\t0x81, 0x3C, 0x01, 0x03, 0x81, 0x3B, 0x01, 0x00, 0x81, 0x3B, 0x00, 0x01,\n-\t0x03, 0x00, 0x31, 0x1A, 0x1B, 0x01, 0x10, 0x11, 0x06, 0x08, 0x01, 0x04,\n-\t0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01, 0x08, 0x11, 0x06, 0x08,\n-\t0x01, 0x03, 0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01, 0x20, 0x11,\n-\t0x06, 0x08, 0x01, 0x05, 0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01,\n-\t0x80, 0x40, 0x11, 0x06, 0x08, 0x01, 0x06, 0x81, 0x3C, 0x02, 0x00, 0x81,\n-\t0x3C, 0x01, 0x04, 0x11, 0x06, 0x08, 0x01, 0x02, 0x81, 0x3C, 0x02, 0x00,\n-\t0x81, 0x3C, 0x00, 0x00, 0x1B, 0x01, 0x08, 0x39, 0x81, 0x3C, 0x81, 0x3C,\n-\t0x00, 0x00, 0x1B, 0x01, 0x10, 0x39, 0x81, 0x3C, 0x81, 0x3A, 0x00, 0x00,\n-\t0x1B, 0x3C, 0x06, 0x02, 0x1A, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x75\n+\t0x41, 0x24, 0x00, 0x00, 0x7A, 0x2C, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01,\n+\t0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x3D, 0x06, 0x04, 0x01, 0x06,\n+\t0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x7F, 0x2C, 0x25, 0x06, 0x08, 0x01,\n+\t0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x24, 0x01, 0x05, 0x00, 0x01,\n+\t0x3E, 0x03, 0x00, 0x24, 0x01, 0x00, 0x40, 0x06, 0x03, 0x02, 0x00, 0x08,\n+\t0x3F, 0x06, 0x03, 0x02, 0x00, 0x08, 0x25, 0x06, 0x06, 0x01, 0x01, 0x0B,\n+\t0x01, 0x06, 0x08, 0x00, 0x00, 0x81, 0x01, 0x3C, 0x25, 0x06, 0x03, 0x01,\n+\t0x09, 0x08, 0x00, 0x01, 0x3D, 0x25, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00,\n+\t0x25, 0x06, 0x0E, 0x25, 0x01, 0x01, 0x17, 0x02, 0x00, 0x08, 0x03, 0x00,\n+\t0x01, 0x01, 0x11, 0x04, 0x6F, 0x24, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01,\n+\t0x06, 0x08, 0x00, 0x00, 0x77, 0x2B, 0x41, 0x11, 0x01, 0x01, 0x17, 0x33,\n+\t0x00, 0x00, 0x81, 0x15, 0x81, 0x42, 0x25, 0x01, 0x07, 0x17, 0x01, 0x00,\n+\t0x36, 0x0E, 0x06, 0x0A, 0x24, 0x01, 0x10, 0x17, 0x06, 0x02, 0x81, 0x15,\n+\t0x04, 0x32, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x29, 0x24, 0x24, 0x01, 0x00,\n+\t0x6F, 0x3B, 0x81, 0x28, 0x7F, 0x2C, 0x01, 0x01, 0x0E, 0x01, 0x01, 0x81,\n+\t0x1E, 0x35, 0x06, 0x11, 0x27, 0x1A, 0x34, 0x06, 0x05, 0x81, 0x42, 0x24,\n+\t0x04, 0x77, 0x01, 0x80, 0x64, 0x81, 0x3A, 0x04, 0x02, 0x81, 0x15, 0x04,\n+\t0x03, 0x6A, 0x26, 0x24, 0x04, 0xFF, 0x35, 0x01, 0x25, 0x03, 0x00, 0x09,\n+\t0x25, 0x50, 0x06, 0x02, 0x60, 0x26, 0x02, 0x00, 0x00, 0x00, 0x81, 0x10,\n+\t0x01, 0x0F, 0x17, 0x00, 0x00, 0x6E, 0x2C, 0x01, 0x00, 0x36, 0x0E, 0x06,\n+\t0x10, 0x24, 0x25, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x24, 0x01, 0x02, 0x6E,\n+\t0x3B, 0x01, 0x00, 0x04, 0x22, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x15, 0x24,\n+\t0x01, 0x00, 0x6E, 0x3B, 0x25, 0x01, 0x80, 0x64, 0x0E, 0x06, 0x05, 0x01,\n+\t0x82, 0x00, 0x08, 0x26, 0x52, 0x00, 0x04, 0x07, 0x24, 0x01, 0x82, 0x00,\n+\t0x08, 0x26, 0x24, 0x00, 0x00, 0x01, 0x00, 0x2D, 0x06, 0x06, 0x38, 0x81,\n+\t0x22, 0x35, 0x04, 0x77, 0x25, 0x06, 0x05, 0x01, 0x01, 0x81, 0x05, 0x3B,\n+\t0x00, 0x00, 0x2D, 0x06, 0x0B, 0x7D, 0x2C, 0x01, 0x14, 0x0D, 0x06, 0x02,\n+\t0x6A, 0x26, 0x04, 0x12, 0x81, 0x42, 0x01, 0x07, 0x17, 0x25, 0x01, 0x02,\n+\t0x0D, 0x06, 0x06, 0x06, 0x02, 0x6A, 0x26, 0x04, 0x6F, 0x24, 0x81, 0x37,\n+\t0x01, 0x01, 0x0D, 0x31, 0x35, 0x06, 0x02, 0x59, 0x26, 0x25, 0x01, 0x01,\n+\t0x81, 0x3D, 0x34, 0x81, 0x27, 0x00, 0x01, 0x81, 0x2D, 0x01, 0x0B, 0x0E,\n+\t0x05, 0x02, 0x6A, 0x26, 0x25, 0x01, 0x03, 0x0E, 0x06, 0x09, 0x81, 0x35,\n+\t0x06, 0x02, 0x60, 0x26, 0x41, 0x24, 0x00, 0x41, 0x4F, 0x81, 0x35, 0x81,\n+\t0x20, 0x25, 0x06, 0x27, 0x81, 0x35, 0x81, 0x20, 0x25, 0x4E, 0x25, 0x06,\n+\t0x19, 0x25, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04,\n+\t0x01, 0x25, 0x03, 0x00, 0x7C, 0x02, 0x00, 0x81, 0x2B, 0x02, 0x00, 0x4B,\n+\t0x04, 0x64, 0x81, 0x11, 0x4C, 0x04, 0x56, 0x81, 0x11, 0x81, 0x11, 0x4D,\n+\t0x25, 0x06, 0x02, 0x33, 0x00, 0x24, 0x29, 0x00, 0x00, 0x71, 0x2A, 0x81,\n+\t0x17, 0x01, 0x7F, 0x81, 0x25, 0x25, 0x50, 0x06, 0x02, 0x33, 0x26, 0x25,\n+\t0x05, 0x02, 0x6A, 0x26, 0x36, 0x17, 0x0D, 0x06, 0x02, 0x6C, 0x26, 0x39,\n+\t0x00, 0x00, 0x81, 0x12, 0x81, 0x2D, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x6A,\n+\t0x26, 0x7C, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x2B, 0x81, 0x11, 0x7C,\n+\t0x25, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x2E, 0x05, 0x02, 0x5C, 0x26, 0x00,\n+\t0x00, 0x81, 0x2E, 0x06, 0x02, 0x6A, 0x26, 0x06, 0x02, 0x5E, 0x26, 0x00,\n+\t0x09, 0x81, 0x2D, 0x01, 0x02, 0x0E, 0x05, 0x02, 0x6A, 0x26, 0x81, 0x34,\n+\t0x03, 0x00, 0x02, 0x00, 0x81, 0x0B, 0x2A, 0x0A, 0x02, 0x00, 0x81, 0x0A,\n+\t0x2A, 0x0F, 0x35, 0x06, 0x02, 0x6B, 0x26, 0x02, 0x00, 0x81, 0x09, 0x2A,\n+\t0x0D, 0x06, 0x02, 0x63, 0x26, 0x02, 0x00, 0x81, 0x0C, 0x3A, 0x81, 0x02,\n+\t0x01, 0x20, 0x81, 0x2B, 0x01, 0x00, 0x03, 0x01, 0x81, 0x36, 0x03, 0x02,\n+\t0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, 0x02, 0x68, 0x26, 0x7C, 0x02, 0x02,\n+\t0x81, 0x2B, 0x02, 0x02, 0x81, 0x04, 0x2C, 0x0E, 0x02, 0x02, 0x01, 0x00,\n+\t0x0F, 0x17, 0x06, 0x0C, 0x81, 0x03, 0x7C, 0x02, 0x02, 0x2E, 0x06, 0x04,\n+\t0x01, 0x7F, 0x03, 0x01, 0x81, 0x03, 0x7C, 0x02, 0x02, 0x2F, 0x02, 0x02,\n+\t0x81, 0x04, 0x3B, 0x02, 0x00, 0x81, 0x08, 0x02, 0x01, 0x81, 0x0E, 0x81,\n+\t0x34, 0x25, 0x81, 0x38, 0x50, 0x06, 0x02, 0x5A, 0x26, 0x71, 0x02, 0x01,\n+\t0x81, 0x0E, 0x81, 0x36, 0x06, 0x02, 0x5B, 0x26, 0x25, 0x06, 0x81, 0x3E,\n+\t0x81, 0x34, 0x81, 0x20, 0x81, 0x1C, 0x03, 0x03, 0x81, 0x1A, 0x03, 0x04,\n+\t0x81, 0x18, 0x03, 0x05, 0x81, 0x1B, 0x03, 0x06, 0x81, 0x1D, 0x03, 0x07,\n+\t0x81, 0x19, 0x03, 0x08, 0x25, 0x06, 0x81, 0x0B, 0x81, 0x34, 0x01, 0x00,\n+\t0x36, 0x0E, 0x06, 0x10, 0x24, 0x02, 0x03, 0x05, 0x02, 0x64, 0x26, 0x01,\n+\t0x00, 0x03, 0x03, 0x81, 0x33, 0x04, 0x80, 0x70, 0x01, 0x01, 0x36, 0x0E,\n+\t0x06, 0x10, 0x24, 0x02, 0x05, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03,\n+\t0x05, 0x81, 0x31, 0x04, 0x80, 0x5A, 0x01, 0x83, 0xFE, 0x01, 0x36, 0x0E,\n+\t0x06, 0x10, 0x24, 0x02, 0x04, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03,\n+\t0x04, 0x81, 0x32, 0x04, 0x80, 0x42, 0x01, 0x0D, 0x36, 0x0E, 0x06, 0x0F,\n+\t0x24, 0x02, 0x06, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03, 0x06, 0x81,\n+\t0x2F, 0x04, 0x2D, 0x01, 0x0A, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x02, 0x07,\n+\t0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03, 0x07, 0x81, 0x2F, 0x04, 0x18,\n+\t0x01, 0x0B, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x02, 0x08, 0x05, 0x02, 0x64,\n+\t0x26, 0x01, 0x00, 0x03, 0x08, 0x81, 0x2F, 0x04, 0x03, 0x64, 0x26, 0x24,\n+\t0x04, 0xFE, 0x71, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F,\n+\t0x06, 0x02, 0x61, 0x26, 0x01, 0x01, 0x7F, 0x3B, 0x81, 0x11, 0x81, 0x11,\n+\t0x02, 0x01, 0x00, 0x04, 0x81, 0x2D, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x6A,\n+\t0x26, 0x81, 0x36, 0x01, 0x03, 0x0E, 0x05, 0x02, 0x65, 0x26, 0x81, 0x34,\n+\t0x25, 0x74, 0x3B, 0x25, 0x01, 0x20, 0x10, 0x06, 0x02, 0x65, 0x26, 0x3D,\n+\t0x41, 0x11, 0x01, 0x01, 0x17, 0x05, 0x02, 0x65, 0x26, 0x81, 0x36, 0x25,\n+\t0x01, 0x81, 0x05, 0x0F, 0x06, 0x02, 0x65, 0x26, 0x25, 0x76, 0x3B, 0x75,\n+\t0x41, 0x81, 0x2B, 0x81, 0x08, 0x2A, 0x01, 0x86, 0x03, 0x10, 0x03, 0x00,\n+\t0x71, 0x2A, 0x81, 0x40, 0x03, 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x00,\n+\t0x06, 0x23, 0x81, 0x36, 0x25, 0x25, 0x01, 0x02, 0x0A, 0x41, 0x01, 0x06,\n+\t0x0F, 0x35, 0x06, 0x02, 0x65, 0x26, 0x03, 0x02, 0x81, 0x36, 0x02, 0x01,\n+\t0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x65, 0x26, 0x04,\n+\t0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0x81, 0x34, 0x25,\n+\t0x03, 0x03, 0x25, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x66, 0x26, 0x7C,\n+\t0x41, 0x81, 0x2B, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x48, 0x25, 0x06,\n+\t0x01, 0x26, 0x24, 0x81, 0x11, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02,\n+\t0x00, 0x81, 0x0D, 0x02, 0x01, 0x02, 0x00, 0x37, 0x25, 0x01, 0x00, 0x0E,\n+\t0x06, 0x02, 0x58, 0x00, 0x81, 0x44, 0x04, 0x73, 0x02, 0x01, 0x00, 0x03,\n+\t0x00, 0x81, 0x36, 0x81, 0x20, 0x25, 0x06, 0x80, 0x44, 0x81, 0x36, 0x01,\n+\t0x01, 0x36, 0x0E, 0x06, 0x06, 0x24, 0x01, 0x81, 0x7F, 0x04, 0x2E, 0x01,\n+\t0x80, 0x40, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x83, 0xFE, 0x00, 0x04,\n+\t0x20, 0x01, 0x80, 0x41, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x84, 0x80,\n+\t0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01,\n+\t0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00, 0x41, 0x24, 0x02, 0x00, 0x35,\n+\t0x03, 0x00, 0x04, 0xFF, 0x38, 0x81, 0x11, 0x71, 0x2A, 0x81, 0x3E, 0x05,\n+\t0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03, 0x00, 0x81, 0x08,\n+\t0x2A, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3B, 0x81, 0x30, 0x25, 0x79, 0x3A,\n+\t0x3E, 0x24, 0x25, 0x01, 0x08, 0x0B, 0x35, 0x01, 0x8C, 0x80, 0x00, 0x35,\n+\t0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17, 0x06,\n+\t0x19, 0x25, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80, 0x00,\n+\t0x35, 0x25, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88, 0x80,\n+\t0x00, 0x35, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88, 0x01,\n+\t0x17, 0x03, 0x00, 0x16, 0x81, 0x34, 0x81, 0x20, 0x25, 0x06, 0x27, 0x81,\n+\t0x34, 0x81, 0x20, 0x25, 0x15, 0x25, 0x06, 0x19, 0x25, 0x01, 0x82, 0x00,\n+\t0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x25, 0x03, 0x01, 0x7C,\n+\t0x02, 0x01, 0x81, 0x2B, 0x02, 0x01, 0x12, 0x04, 0x64, 0x81, 0x11, 0x13,\n+\t0x04, 0x56, 0x81, 0x11, 0x14, 0x81, 0x11, 0x02, 0x00, 0x28, 0x00, 0x00,\n+\t0x81, 0x2E, 0x25, 0x52, 0x06, 0x07, 0x24, 0x06, 0x02, 0x5E, 0x26, 0x04,\n+\t0x73, 0x00, 0x00, 0x81, 0x37, 0x01, 0x03, 0x81, 0x35, 0x41, 0x24, 0x41,\n+\t0x00, 0x00, 0x81, 0x34, 0x81, 0x3B, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00,\n+\t0x81, 0x34, 0x81, 0x20, 0x25, 0x06, 0x34, 0x81, 0x36, 0x03, 0x01, 0x81,\n+\t0x36, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01, 0x01, 0x06,\n+\t0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01, 0x03, 0x0E,\n+\t0x35, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x55, 0x01,\n+\t0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x35, 0x03, 0x00, 0x04, 0x49, 0x81,\n+\t0x11, 0x02, 0x00, 0x00, 0x00, 0x81, 0x34, 0x01, 0x01, 0x0E, 0x05, 0x02,\n+\t0x5D, 0x26, 0x81, 0x36, 0x01, 0x08, 0x08, 0x7A, 0x2C, 0x0E, 0x05, 0x02,\n+\t0x5D, 0x26, 0x00, 0x00, 0x81, 0x34, 0x7F, 0x2C, 0x05, 0x16, 0x01, 0x01,\n+\t0x0E, 0x05, 0x02, 0x61, 0x26, 0x81, 0x36, 0x01, 0x00, 0x0E, 0x05, 0x02,\n+\t0x61, 0x26, 0x01, 0x02, 0x7F, 0x3B, 0x04, 0x1F, 0x01, 0x19, 0x0E, 0x05,\n+\t0x02, 0x61, 0x26, 0x81, 0x36, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x61, 0x26,\n+\t0x7C, 0x01, 0x18, 0x81, 0x2B, 0x81, 0x00, 0x7C, 0x01, 0x18, 0x2E, 0x05,\n+\t0x02, 0x61, 0x26, 0x00, 0x00, 0x81, 0x34, 0x06, 0x02, 0x62, 0x26, 0x00,\n+\t0x00, 0x01, 0x02, 0x81, 0x0D, 0x81, 0x37, 0x01, 0x08, 0x0B, 0x81, 0x37,\n+\t0x08, 0x00, 0x00, 0x01, 0x03, 0x81, 0x0D, 0x81, 0x37, 0x01, 0x08, 0x0B,\n+\t0x81, 0x37, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x37, 0x08, 0x00, 0x00, 0x01,\n+\t0x01, 0x81, 0x0D, 0x81, 0x37, 0x00, 0x00, 0x38, 0x25, 0x50, 0x05, 0x01,\n+\t0x00, 0x24, 0x81, 0x44, 0x04, 0x75, 0x02, 0x03, 0x00, 0x81, 0x07, 0x2C,\n+\t0x03, 0x01, 0x01, 0x00, 0x25, 0x02, 0x01, 0x0A, 0x06, 0x11, 0x25, 0x01,\n+\t0x01, 0x0B, 0x81, 0x06, 0x08, 0x2A, 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00,\n+\t0x54, 0x04, 0x69, 0x24, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x15, 0x7E, 0x3B,\n+\t0x41, 0x4A, 0x24, 0x4A, 0x24, 0x27, 0x00, 0x00, 0x01, 0x01, 0x41, 0x81,\n+\t0x39, 0x00, 0x00, 0x41, 0x36, 0x81, 0x0D, 0x41, 0x25, 0x06, 0x06, 0x81,\n+\t0x37, 0x24, 0x55, 0x04, 0x77, 0x24, 0x00, 0x00, 0x25, 0x01, 0x81, 0xAC,\n+\t0x00, 0x0E, 0x06, 0x04, 0x24, 0x01, 0x7F, 0x00, 0x81, 0x10, 0x51, 0x00,\n+\t0x02, 0x03, 0x00, 0x71, 0x2A, 0x81, 0x10, 0x03, 0x01, 0x02, 0x01, 0x01,\n+\t0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02, 0x01,\n+\t0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x36, 0x0E, 0x06, 0x10,\n+\t0x24, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01,\n+\t0x45, 0x04, 0x80, 0x56, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x10, 0x24, 0x01,\n+\t0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01, 0x45, 0x04,\n+\t0x80, 0x40, 0x01, 0x02, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x01, 0x01, 0x01,\n+\t0x20, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01, 0x45, 0x04, 0x2B, 0x01,\n+\t0x03, 0x36, 0x0E, 0x06, 0x0E, 0x24, 0x24, 0x01, 0x10, 0x02, 0x00, 0x06,\n+\t0x03, 0x42, 0x04, 0x01, 0x43, 0x04, 0x17, 0x01, 0x04, 0x36, 0x0E, 0x06,\n+\t0x0E, 0x24, 0x24, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x42, 0x04, 0x01,\n+\t0x43, 0x04, 0x03, 0x60, 0x26, 0x24, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C,\n+\t0x11, 0x01, 0x02, 0x0F, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x25,\n+\t0x53, 0x41, 0x01, 0x03, 0x0A, 0x17, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C,\n+\t0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x52,\n+\t0x00, 0x00, 0x1B, 0x01, 0x00, 0x6D, 0x2C, 0x25, 0x06, 0x20, 0x01, 0x01,\n+\t0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x00, 0x81, 0x14, 0x04, 0x11, 0x01,\n+\t0x02, 0x36, 0x0E, 0x06, 0x0A, 0x24, 0x6F, 0x2C, 0x06, 0x03, 0x01, 0x10,\n+\t0x35, 0x04, 0x01, 0x24, 0x04, 0x01, 0x24, 0x73, 0x2C, 0x05, 0x35, 0x2D,\n+\t0x06, 0x32, 0x7D, 0x2C, 0x01, 0x14, 0x36, 0x0E, 0x06, 0x06, 0x24, 0x01,\n+\t0x02, 0x35, 0x04, 0x24, 0x01, 0x15, 0x36, 0x0E, 0x06, 0x0B, 0x24, 0x81,\n+\t0x23, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x14, 0x04, 0x13, 0x01, 0x16, 0x36,\n+\t0x0E, 0x06, 0x06, 0x24, 0x01, 0x01, 0x35, 0x04, 0x07, 0x24, 0x01, 0x04,\n+\t0x35, 0x01, 0x00, 0x24, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x35, 0x00, 0x00,\n+\t0x1B, 0x25, 0x05, 0x10, 0x2D, 0x06, 0x0D, 0x7D, 0x2C, 0x01, 0x15, 0x0E,\n+\t0x06, 0x05, 0x24, 0x81, 0x23, 0x04, 0x01, 0x1F, 0x00, 0x00, 0x81, 0x42,\n+\t0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02, 0x6A, 0x26, 0x00, 0x01,\n+\t0x03, 0x00, 0x27, 0x1A, 0x06, 0x05, 0x02, 0x00, 0x7E, 0x3B, 0x00, 0x81,\n+\t0x42, 0x24, 0x04, 0x73, 0x00, 0x01, 0x14, 0x81, 0x45, 0x01, 0x01, 0x81,\n+\t0x52, 0x27, 0x25, 0x01, 0x00, 0x81, 0x3D, 0x01, 0x16, 0x81, 0x45, 0x81,\n+\t0x4B, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x52, 0x46, 0x25, 0x25, 0x01,\n+\t0x03, 0x08, 0x81, 0x51, 0x81, 0x51, 0x18, 0x25, 0x50, 0x06, 0x02, 0x24,\n+\t0x00, 0x81, 0x51, 0x1D, 0x25, 0x06, 0x06, 0x7C, 0x41, 0x81, 0x4C, 0x04,\n+\t0x76, 0x24, 0x04, 0x6A, 0x00, 0x20, 0x01, 0x0F, 0x81, 0x52, 0x25, 0x81,\n+\t0x08, 0x2A, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0F, 0x01, 0x04, 0x08, 0x81,\n+\t0x51, 0x78, 0x2C, 0x81, 0x52, 0x70, 0x2C, 0x81, 0x52, 0x04, 0x03, 0x56,\n+\t0x81, 0x51, 0x25, 0x81, 0x50, 0x7C, 0x41, 0x81, 0x4C, 0x00, 0x02, 0x81,\n+\t0x1A, 0x81, 0x1C, 0x08, 0x81, 0x18, 0x08, 0x81, 0x1B, 0x08, 0x81, 0x1D,\n+\t0x08, 0x81, 0x19, 0x08, 0x03, 0x00, 0x01, 0x01, 0x81, 0x52, 0x01, 0x27,\n+\t0x81, 0x04, 0x2C, 0x08, 0x81, 0x07, 0x2C, 0x01, 0x01, 0x0B, 0x08, 0x02,\n+\t0x00, 0x06, 0x04, 0x56, 0x02, 0x00, 0x08, 0x7B, 0x2A, 0x36, 0x09, 0x25,\n+\t0x53, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x41, 0x56, 0x41, 0x57, 0x01,\n+\t0x04, 0x09, 0x25, 0x50, 0x06, 0x03, 0x24, 0x01, 0x00, 0x25, 0x01, 0x04,\n+\t0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x41, 0x01, 0x04, 0x08, 0x36, 0x08,\n+\t0x41, 0x04, 0x03, 0x24, 0x01, 0x7F, 0x03, 0x01, 0x81, 0x51, 0x81, 0x0A,\n+\t0x2A, 0x81, 0x50, 0x72, 0x01, 0x04, 0x19, 0x72, 0x01, 0x04, 0x08, 0x01,\n+\t0x1C, 0x30, 0x72, 0x01, 0x20, 0x81, 0x4C, 0x81, 0x03, 0x81, 0x04, 0x2C,\n+\t0x81, 0x4E, 0x81, 0x07, 0x2C, 0x25, 0x01, 0x01, 0x0B, 0x81, 0x50, 0x81,\n+\t0x06, 0x41, 0x25, 0x06, 0x11, 0x55, 0x36, 0x2A, 0x25, 0x81, 0x3C, 0x05,\n+\t0x02, 0x5A, 0x26, 0x81, 0x50, 0x41, 0x56, 0x41, 0x04, 0x6C, 0x58, 0x01,\n+\t0x01, 0x81, 0x52, 0x01, 0x00, 0x81, 0x52, 0x02, 0x00, 0x06, 0x81, 0x49,\n+\t0x02, 0x00, 0x81, 0x50, 0x81, 0x1A, 0x06, 0x13, 0x01, 0x83, 0xFE, 0x01,\n+\t0x81, 0x50, 0x81, 0x00, 0x81, 0x1A, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50,\n+\t0x55, 0x81, 0x4E, 0x81, 0x1C, 0x06, 0x1D, 0x01, 0x00, 0x81, 0x50, 0x81,\n+\t0x01, 0x81, 0x1C, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x01, 0x02, 0x09,\n+\t0x25, 0x81, 0x50, 0x01, 0x00, 0x81, 0x52, 0x01, 0x03, 0x09, 0x81, 0x4D,\n+\t0x81, 0x18, 0x06, 0x0F, 0x01, 0x01, 0x81, 0x50, 0x01, 0x01, 0x81, 0x50,\n+\t0x7A, 0x2C, 0x01, 0x08, 0x09, 0x81, 0x52, 0x81, 0x1B, 0x06, 0x1F, 0x01,\n+\t0x0D, 0x81, 0x50, 0x81, 0x1B, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x01,\n+\t0x02, 0x09, 0x81, 0x50, 0x3F, 0x06, 0x04, 0x01, 0x03, 0x81, 0x4F, 0x40,\n+\t0x06, 0x04, 0x01, 0x01, 0x81, 0x4F, 0x81, 0x1D, 0x25, 0x06, 0x27, 0x01,\n+\t0x0A, 0x81, 0x50, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x57, 0x81, 0x50,\n+\t0x3D, 0x01, 0x00, 0x25, 0x01, 0x20, 0x0A, 0x06, 0x0E, 0x81, 0x16, 0x11,\n+\t0x01, 0x01, 0x17, 0x06, 0x03, 0x25, 0x81, 0x50, 0x54, 0x04, 0x6C, 0x58,\n+\t0x04, 0x01, 0x24, 0x81, 0x19, 0x06, 0x0D, 0x01, 0x0B, 0x81, 0x50, 0x01,\n+\t0x02, 0x81, 0x50, 0x01, 0x82, 0x00, 0x81, 0x50, 0x02, 0x01, 0x50, 0x05,\n+\t0x14, 0x01, 0x15, 0x81, 0x50, 0x02, 0x01, 0x25, 0x81, 0x50, 0x25, 0x06,\n+\t0x07, 0x55, 0x01, 0x00, 0x81, 0x52, 0x04, 0x76, 0x24, 0x00, 0x00, 0x01,\n+\t0x10, 0x81, 0x52, 0x71, 0x2A, 0x25, 0x81, 0x41, 0x06, 0x10, 0x81, 0x21,\n+\t0x22, 0x25, 0x56, 0x81, 0x51, 0x25, 0x81, 0x50, 0x7C, 0x41, 0x81, 0x4C,\n+\t0x04, 0x12, 0x25, 0x81, 0x3F, 0x41, 0x81, 0x21, 0x21, 0x25, 0x54, 0x81,\n+\t0x51, 0x25, 0x81, 0x52, 0x7C, 0x41, 0x81, 0x4C, 0x00, 0x00, 0x81, 0x12,\n+\t0x01, 0x14, 0x81, 0x52, 0x01, 0x0C, 0x81, 0x51, 0x7C, 0x01, 0x0C, 0x81,\n+\t0x4C, 0x00, 0x00, 0x49, 0x25, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x58, 0x00,\n+\t0x81, 0x42, 0x24, 0x04, 0x72, 0x00, 0x25, 0x81, 0x50, 0x81, 0x4C, 0x00,\n+\t0x00, 0x25, 0x81, 0x52, 0x81, 0x4C, 0x00, 0x01, 0x03, 0x00, 0x3E, 0x24,\n+\t0x25, 0x01, 0x10, 0x17, 0x06, 0x08, 0x01, 0x04, 0x81, 0x52, 0x02, 0x00,\n+\t0x81, 0x52, 0x25, 0x01, 0x08, 0x17, 0x06, 0x08, 0x01, 0x03, 0x81, 0x52,\n+\t0x02, 0x00, 0x81, 0x52, 0x25, 0x01, 0x20, 0x17, 0x06, 0x08, 0x01, 0x05,\n+\t0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x25, 0x01, 0x80, 0x40, 0x17, 0x06,\n+\t0x08, 0x01, 0x06, 0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x01, 0x04, 0x17,\n+\t0x06, 0x08, 0x01, 0x02, 0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x00, 0x00,\n+\t0x25, 0x01, 0x08, 0x47, 0x81, 0x52, 0x81, 0x52, 0x00, 0x00, 0x25, 0x01,\n+\t0x10, 0x47, 0x81, 0x52, 0x81, 0x50, 0x00, 0x00, 0x25, 0x4A, 0x06, 0x02,\n+\t0x24, 0x00, 0x81, 0x42, 0x24, 0x04, 0x75\n };\n \n static const uint16_t t0_caddr[] \u003d {\n@@ -670,103 +784,111 @@ static const uint16_t t0_caddr[] \u003d {\n \t112,\n \t116,\n \t120,\n-\t125,\n-\t130,\n-\t135,\n-\t140,\n-\t145,\n-\t150,\n-\t155,\n-\t160,\n-\t165,\n-\t170,\n-\t175,\n-\t180,\n-\t185,\n-\t190,\n-\t195,\n-\t200,\n-\t205,\n-\t210,\n-\t215,\n-\t220,\n-\t225,\n-\t230,\n-\t235,\n-\t240,\n-\t245,\n-\t250,\n-\t255,\n-\t260,\n-\t265,\n+\t124,\n+\t129,\n+\t134,\n+\t139,\n+\t144,\n+\t149,\n+\t154,\n+\t159,\n+\t164,\n+\t169,\n+\t174,\n+\t179,\n+\t184,\n+\t189,\n+\t194,\n+\t199,\n+\t204,\n+\t209,\n+\t214,\n+\t219,\n+\t224,\n+\t229,\n+\t234,\n+\t239,\n+\t244,\n+\t249,\n+\t254,\n+\t259,\n+\t264,\n+\t269,\n \t274,\n-\t287,\n-\t291,\n-\t318,\n-\t324,\n+\t279,\n+\t284,\n+\t293,\n+\t306,\n+\t310,\n+\t338,\n \t344,\n-\t355,\n-\t392,\n-\t495,\n-\t499,\n-\t564,\n-\t579,\n-\t590,\n-\t608,\n-\t637,\n-\t647,\n-\t683,\n-\t693,\n-\t771,\n-\t785,\n-\t791,\n-\t851,\n-\t871,\n-\t924,\n-\t993,\n-\t1027,\n-\t1039,\n-\t1364,\n-\t1521,\n-\t1546,\n-\t1557,\n-\t1572,\n-\t1583,\n-\t1589,\n-\t1612,\n-\t1672,\n-\t1680,\n-\t1693,\n-\t1712,\n-\t1719,\n-\t1731,\n-\t1766,\n-\t1778,\n-\t1785,\n-\t1801,\n-\t1817,\n-\t1955,\n-\t1968,\n-\t1977,\n-\t1984,\n-\t2090,\n-\t2112,\n-\t2126,\n-\t2143,\n-\t2166,\n-\t2529,\n-\t2576,\n-\t2593,\n-\t2608,\n-\t2615,\n-\t2622,\n-\t2636,\n-\t2712,\n-\t2722,\n-\t2732\n+\t365,\n+\t376,\n+\t413,\n+\t548,\n+\t552,\n+\t618,\n+\t633,\n+\t644,\n+\t662,\n+\t691,\n+\t702,\n+\t738,\n+\t748,\n+\t826,\n+\t840,\n+\t847,\n+\t907,\n+\t928,\n+\t981,\n+\t1067,\n+\t1096,\n+\t1131,\n+\t1143,\n+\t1482,\n+\t1641,\n+\t1667,\n+\t1898,\n+\t1913,\n+\t1924,\n+\t1930,\n+\t1999,\n+\t2022,\n+\t2083,\n+\t2091,\n+\t2105,\n+\t2125,\n+\t2133,\n+\t2145,\n+\t2182,\n+\t2194,\n+\t2201,\n+\t2218,\n+\t2235,\n+\t2374,\n+\t2384,\n+\t2398,\n+\t2408,\n+\t2416,\n+\t2522,\n+\t2544,\n+\t2558,\n+\t2575,\n+\t2598,\n+\t2635,\n+\t2677,\n+\t3049,\n+\t3096,\n+\t3113,\n+\t3128,\n+\t3135,\n+\t3142,\n+\t3218,\n+\t3228,\n+\t3238\n };\n \n-#define T0_INTERPRETED 66\n+#define T0_INTERPRETED 80\n \n #define T0_ENTER(ip, rp, slot) do { \u005c\n \t\tconst unsigned char *t0_newip; \u005c\n@@ -787,7 +909,7 @@ name(void *ctx) \u005c\n \tT0_ENTER(t0ctx-\u003eip, t0ctx-\u003erp, slot); \u005c\n }\n \n-T0_DEFENTRY(br_ssl_hs_client_init_main, 141)\n+T0_DEFENTRY(br_ssl_hs_client_init_main, 159)\n \n void\n br_ssl_hs_client_run(void *t0ctx)\n@@ -930,6 +1052,15 @@ br_ssl_hs_client_run(void *t0ctx)\n \t\t\t\t}\n \t\t\t\tbreak;\n \t\t\tcase 12: {\n+\t\t\t\t/* \u003c\u003d */\n+\n+\tint32_t b \u003d T0_POPi();\n+\tint32_t a \u003d T0_POPi();\n+\tT0_PUSH(-(uint32_t)(a \u003c\u003d b));\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 13: {\n \t\t\t\t/* \u003c\u003e */\n \n \tuint32_t b \u003d T0_POP();\n@@ -938,7 +1069,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 13: {\n+\t\t\tcase 14: {\n \t\t\t\t/* \u003d */\n \n \tuint32_t b \u003d T0_POP();\n@@ -947,7 +1078,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 14: {\n+\t\t\tcase 15: {\n \t\t\t\t/* \u003e */\n \n \tint32_t b \u003d T0_POPi();\n@@ -956,7 +1087,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 15: {\n+\t\t\tcase 16: {\n \t\t\t\t/* \u003e\u003d */\n \n \tint32_t b \u003d T0_POPi();\n@@ -965,7 +1096,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 16: {\n+\t\t\tcase 17: {\n \t\t\t\t/* \u003e\u003e */\n \n \tint c \u003d (int)T0_POPi();\n@@ -974,7 +1105,63 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 17: {\n+\t\t\tcase 18: {\n+\t\t\t\t/* anchor-dn-append-name */\n+\n+\tsize_t len;\n+\n+\tlen \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eappend_name(\n+\t\t\tCTX-\u003eclient_auth_vtable, ENG-\u003epad, len);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 19: {\n+\t\t\t\t/* anchor-dn-end-name */\n+\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eend_name(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 20: {\n+\t\t\t\t/* anchor-dn-end-name-list */\n+\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eend_name_list(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 21: {\n+\t\t\t\t/* anchor-dn-start-name */\n+\n+\tsize_t len;\n+\n+\tlen \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003estart_name(\n+\t\t\tCTX-\u003eclient_auth_vtable, len);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 22: {\n+\t\t\t\t/* anchor-dn-start-name-list */\n+\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003estart_name_list(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 23: {\n \t\t\t\t/* and */\n \n \tuint32_t b \u003d T0_POP();\n@@ -983,7 +1170,22 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 18: {\n+\t\t\tcase 24: {\n+\t\t\t\t/* begin-cert */\n+\n+\tif (ENG-\u003echain_len \u003d\u003d 0) {\n+\t\tT0_PUSHi(-1);\n+\t} else {\n+\t\tENG-\u003ecert_cur \u003d ENG-\u003echain-\u003edata;\n+\t\tENG-\u003ecert_len \u003d ENG-\u003echain-\u003edata_len;\n+\t\tENG-\u003echain ++;\n+\t\tENG-\u003echain_len --;\n+\t\tT0_PUSH(ENG-\u003ecert_len);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 25: {\n \t\t\t\t/* bzero */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -992,19 +1194,19 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 19: {\n+\t\t\tcase 26: {\n \t\t\t\t/* can-output? */\n \n \tT0_PUSHi(-(ENG-\u003ehlen_out \u003e 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 20: {\n+\t\t\tcase 27: {\n \t\t\t\t/* co */\n T0_CO(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 21: {\n+\t\t\tcase 28: {\n \t\t\t\t/* compute-Finished-inner */\n \n \tint prf_id \u003d T0_POP();\n@@ -1027,7 +1229,23 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 22: {\n+\t\t\tcase 29: {\n+\t\t\t\t/* copy-cert-chunk */\n+\n+\tsize_t clen;\n+\n+\tclen \u003d ENG-\u003ecert_len;\n+\tif (clen \u003e sizeof ENG-\u003epad) {\n+\t\tclen \u003d sizeof ENG-\u003epad;\n+\t}\n+\tmemcpy(ENG-\u003epad, ENG-\u003ecert_cur, clen);\n+\tENG-\u003ecert_cur +\u003d clen;\n+\tENG-\u003ecert_len -\u003d clen;\n+\tT0_PUSH(clen);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 30: {\n \t\t\t\t/* data-get8 */\n \n \tsize_t addr \u003d T0_POP();\n@@ -1035,14 +1253,28 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 23: {\n+\t\t\tcase 31: {\n \t\t\t\t/* discard-input */\n \n \tENG-\u003ehlen_in \u003d 0;\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 24: {\n+\t\t\tcase 32: {\n+\t\t\t\t/* do-client-sign */\n+\n+\tsize_t sig_len;\n+\n+\tsig_len \u003d make_client_sign(CTX);\n+\tif (sig_len \u003d\u003d 0) {\n+\t\tbr_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);\n+\t\tT0_CO();\n+\t}\n+\tT0_PUSH(sig_len);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 33: {\n \t\t\t\t/* do-ecdh */\n \n \tunsigned prf_id \u003d T0_POP();\n@@ -1059,7 +1291,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 25: {\n+\t\t\tcase 34: {\n \t\t\t\t/* do-rsa-encrypt */\n \n \tint x;\n@@ -1074,17 +1306,29 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 26: {\n+\t\t\tcase 35: {\n+\t\t\t\t/* do-static-ecdh */\n+\n+\tunsigned prf_id \u003d T0_POP();\n+\n+\tif (make_pms_static_ecdh(CTX, prf_id) \u003c 0) {\n+\t\tbr_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);\n+\t\tT0_CO();\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 36: {\n \t\t\t\t/* drop */\n (void)T0_POP(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 27: {\n+\t\t\tcase 37: {\n \t\t\t\t/* dup */\n T0_PUSH(T0_PEEK(0)); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 28: {\n+\t\t\tcase 38: {\n \t\t\t\t/* fail */\n \n \tbr_ssl_engine_fail(ENG, (int)T0_POPi());\n@@ -1092,14 +1336,53 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 29: {\n+\t\t\tcase 39: {\n \t\t\t\t/* flush-record */\n \n \tbr_ssl_engine_flush_record(ENG);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 30: {\n+\t\t\tcase 40: {\n+\t\t\t\t/* get-client-chain */\n+\n+\tuint32_t auth_types;\n+\n+\tauth_types \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\tbr_ssl_client_certificate ux;\n+\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003echoose(CTX-\u003eclient_auth_vtable,\n+\t\t\tCTX, auth_types, \u0026ux);\n+\t\tCTX-\u003eauth_type \u003d (unsigned char)ux.auth_type;\n+\t\tCTX-\u003ehash_id \u003d (unsigned char)ux.hash_id;\n+\t\tENG-\u003echain \u003d ux.chain;\n+\t\tENG-\u003echain_len \u003d ux.chain_len;\n+\t} else {\n+\t\tCTX-\u003ehash_id \u003d 0;\n+\t\tENG-\u003echain_len \u003d 0;\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 41: {\n+\t\t\t\t/* get-key-type-usages */\n+\n+\tconst br_x509_class *xc;\n+\tconst br_x509_pkey *pk;\n+\tunsigned usages;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tpk \u003d xc-\u003eget_pkey(ENG-\u003ex509ctx, \u0026usages);\n+\tif (pk \u003d\u003d NULL) {\n+\t\tT0_PUSH(0);\n+\t} else {\n+\t\tT0_PUSH(pk-\u003ekey_type | usages);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 42: {\n \t\t\t\t/* get16 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1107,7 +1390,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 31: {\n+\t\t\tcase 43: {\n \t\t\t\t/* get32 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1115,7 +1398,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 32: {\n+\t\t\tcase 44: {\n \t\t\t\t/* get8 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1123,14 +1406,14 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 33: {\n+\t\t\tcase 45: {\n \t\t\t\t/* has-input? */\n \n \tT0_PUSHi(-(ENG-\u003ehlen_in !\u003d 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 34: {\n+\t\t\tcase 46: {\n \t\t\t\t/* memcmp */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1141,7 +1424,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 35: {\n+\t\t\tcase 47: {\n \t\t\t\t/* memcpy */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1151,7 +1434,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 36: {\n+\t\t\tcase 48: {\n \t\t\t\t/* mkrand */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1160,21 +1443,21 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 37: {\n+\t\t\tcase 49: {\n \t\t\t\t/* more-incoming-bytes? */\n \n \tT0_PUSHi(ENG-\u003ehlen_in !\u003d 0 || !br_ssl_engine_recvrec_finished(ENG));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 38: {\n+\t\t\tcase 50: {\n \t\t\t\t/* multihash-init */\n \n \tbr_multihash_init(\u0026ENG-\u003emhash);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 39: {\n+\t\t\tcase 51: {\n \t\t\t\t/* neg */\n \n \tuint32_t a \u003d T0_POP();\n@@ -1182,7 +1465,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 40: {\n+\t\t\tcase 52: {\n \t\t\t\t/* not */\n \n \tuint32_t a \u003d T0_POP();\n@@ -1190,7 +1473,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 41: {\n+\t\t\tcase 53: {\n \t\t\t\t/* or */\n \n \tuint32_t b \u003d T0_POP();\n@@ -1199,12 +1482,12 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 42: {\n+\t\t\tcase 54: {\n \t\t\t\t/* over */\n T0_PUSH(T0_PEEK(1)); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 43: {\n+\t\t\tcase 55: {\n \t\t\t\t/* read-chunk-native */\n \n \tsize_t clen \u003d ENG-\u003ehlen_in;\n@@ -1228,7 +1511,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 44: {\n+\t\t\tcase 56: {\n \t\t\t\t/* read8-native */\n \n \tif (ENG-\u003ehlen_in \u003e 0) {\n@@ -1246,7 +1529,20 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 45: {\n+\t\t\tcase 57: {\n+\t\t\t\t/* set-server-curve */\n+\n+\tconst br_x509_class *xc;\n+\tconst br_x509_pkey *pk;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tpk \u003d xc-\u003eget_pkey(ENG-\u003ex509ctx, NULL);\n+\tCTX-\u003eserver_curve \u003d\n+\t\t(pk-\u003ekey_type \u003d\u003d BR_KEYTYPE_EC) ? pk-\u003ekey.ec.curve : 0;\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 58: {\n \t\t\t\t/* set16 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1254,7 +1550,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 46: {\n+\t\t\tcase 59: {\n \t\t\t\t/* set8 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1262,7 +1558,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 47: {\n+\t\t\tcase 60: {\n \t\t\t\t/* strlen */\n \n \tvoid *str \u003d (unsigned char *)ENG + (size_t)T0_POP();\n@@ -1270,7 +1566,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 48: {\n+\t\t\tcase 61: {\n \t\t\t\t/* supported-curves */\n \n \tuint32_t x \u003d ENG-\u003eiec \u003d\u003d NULL ? 0 : ENG-\u003eiec-\u003esupported_curves;\n@@ -1278,7 +1574,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 49: {\n+\t\t\tcase 62: {\n \t\t\t\t/* supported-hash-functions */\n \n \tint i;\n@@ -1297,26 +1593,26 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 50: {\n+\t\t\tcase 63: {\n \t\t\t\t/* supports-ecdsa? */\n \n-\tT0_PUSHi(-(CTX-\u003eiecdsa !\u003d 0));\n+\tT0_PUSHi(-(ENG-\u003eiecdsa !\u003d 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 51: {\n+\t\t\tcase 64: {\n \t\t\t\t/* supports-rsa-sign? */\n \n-\tT0_PUSHi(-(CTX-\u003eirsavrfy !\u003d 0));\n+\tT0_PUSHi(-(ENG-\u003eirsavrfy !\u003d 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 52: {\n+\t\t\tcase 65: {\n \t\t\t\t/* swap */\n T0_SWAP(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 53: {\n+\t\t\tcase 66: {\n \t\t\t\t/* switch-aesgcm-in */\n \n \tint is_client, prf_id;\n@@ -1330,7 +1626,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 54: {\n+\t\t\tcase 67: {\n \t\t\t\t/* switch-aesgcm-out */\n \n \tint is_client, prf_id;\n@@ -1344,7 +1640,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 55: {\n+\t\t\tcase 68: {\n \t\t\t\t/* switch-cbc-in */\n \n \tint is_client, prf_id, mac_id, aes;\n@@ -1360,7 +1656,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 56: {\n+\t\t\tcase 69: {\n \t\t\t\t/* switch-cbc-out */\n \n \tint is_client, prf_id, mac_id, aes;\n@@ -1376,7 +1672,21 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 57: {\n+\t\t\tcase 70: {\n+\t\t\t\t/* total-chain-length */\n+\n+\tsize_t u;\n+\tuint32_t total;\n+\n+\ttotal \u003d 0;\n+\tfor (u \u003d 0; u \u003c ENG-\u003echain_len; u ++) {\n+\t\ttotal +\u003d 3 + (uint32_t)ENG-\u003echain[u].data_len;\n+\t}\n+\tT0_PUSH(total);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 71: {\n \t\t\t\t/* u\u003e\u003e */\n \n \tint c \u003d (int)T0_POPi();\n@@ -1385,7 +1695,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 58: {\n+\t\t\tcase 72: {\n \t\t\t\t/* verify-SKE-sig */\n \n \tsize_t sig_len \u003d T0_POP();\n@@ -1396,7 +1706,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 59: {\n+\t\t\tcase 73: {\n \t\t\t\t/* write-blob-chunk */\n \n \tsize_t clen \u003d ENG-\u003ehlen_out;\n@@ -1420,7 +1730,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 60: {\n+\t\t\tcase 74: {\n \t\t\t\t/* write8-native */\n \n \tunsigned char x;\n@@ -1439,7 +1749,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 61: {\n+\t\t\tcase 75: {\n \t\t\t\t/* x509-append */\n \n \tconst br_x509_class *xc;\n@@ -1451,7 +1761,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 62: {\n+\t\t\tcase 76: {\n \t\t\t\t/* x509-end-cert */\n \n \tconst br_x509_class *xc;\n@@ -1461,7 +1771,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 63: {\n+\t\t\tcase 77: {\n \t\t\t\t/* x509-end-chain */\n \n \tconst br_x509_class *xc;\n@@ -1471,7 +1781,7 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 64: {\n+\t\t\tcase 78: {\n \t\t\t\t/* x509-start-cert */\n \n \tconst br_x509_class *xc;\n@@ -1481,13 +1791,15 @@ br_ssl_hs_client_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 65: {\n+\t\t\tcase 79: {\n \t\t\t\t/* x509-start-chain */\n \n \tconst br_x509_class *xc;\n+\tuint32_t bc;\n \n+\tbc \u003d T0_POP();\n \txc \u003d *(ENG-\u003ex509ctx);\n-\txc-\u003estart_chain(ENG-\u003ex509ctx, T0_POP(), ENG-\u003eserver_name);\n+\txc-\u003estart_chain(ENG-\u003ex509ctx, bc ? ENG-\u003eserver_name : NULL);\n \n \t\t\t\t}\n \t\t\t\tbreak;\ndiff --git a/src/ssl/ssl_hs_client.t0 b/src/ssl/ssl_hs_client.t0\nindex ea9f5b5..37c554c 100644\n--- a/src/ssl/ssl_hs_client.t0\n+++ b/src/ssl/ssl_hs_client.t0\n@@ -55,7 +55,7 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)\n \tsize_t nlen, u;\n \n \txc \u003d ctx-\u003eeng.x509ctx;\n-\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \n \t/*\n \t * Compute actual RSA key length, in case there are leading zeros.\n@@ -145,9 +145,11 @@ static const unsigned char *HASH_OID[] \u003d {\n \n /*\n * Check the RSA signature on the ServerKeyExchange message.\n+ *\n * hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)\n * use_rsa non-zero for RSA signature, zero for ECDSA\n * sig_len signature length (in bytes); signature value is in the pad\n+ *\n * Returned value is 0 on success, or an error code.\n */\n static int\n@@ -161,7 +163,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n \tsize_t hv_len;\n \n \txc \u003d ctx-\u003eeng.x509ctx;\n-\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \tbr_multihash_zero(\u0026mhc);\n \tbr_multihash_copyimpl(\u0026mhc, \u0026ctx-\u003eeng.mhash);\n \tbr_multihash_init(\u0026mhc);\n@@ -198,14 +200,14 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n \t\t} else {\n \t\t\thash_oid \u003d NULL;\n \t\t}\n-\t\tif (!ctx-\u003eirsavrfy(ctx-\u003eeng.pad, sig_len,\n+\t\tif (!ctx-\u003eeng.irsavrfy(ctx-\u003eeng.pad, sig_len,\n \t\t\thash_oid, hv_len, \u0026pk-\u003ekey.rsa, tmp)\n \t\t\t|| memcmp(tmp, hv, hv_len) !\u003d 0)\n \t\t{\n \t\t\treturn BR_ERR_BAD_SIGNATURE;\n \t\t}\n \t} else {\n-\t\tif (!ctx-\u003eiecdsa(ctx-\u003eeng.iec, hv, hv_len, \u0026pk-\u003ekey.ec,\n+\t\tif (!ctx-\u003eeng.iecdsa(ctx-\u003eeng.iec, hv, hv_len, \u0026pk-\u003ekey.ec,\n \t\t\tctx-\u003eeng.pad, sig_len))\n \t\t{\n \t\t\treturn BR_ERR_BAD_SIGNATURE;\n@@ -215,7 +217,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,\n }\n \n /*\n- * Perform client-size ECDH (or ECDHE). The point that should be sent to\n+ * Perform client-side ECDH (or ECDHE). The point that should be sent to\n * the server is written in the pad; returned value is either the point\n * length (in bytes), or -x on error, with 'x' being an error code.\n *\n@@ -241,7 +243,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)\n \t\tconst br_x509_pkey *pk;\n \n \t\txc \u003d ctx-\u003eeng.x509ctx;\n-\t\tpk \u003d (*xc)-\u003eget_pkey(xc);\n+\t\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n \t\tcurve \u003d pk-\u003ekey.ec.curve;\n \t\tpoint_src \u003d pk-\u003ekey.ec.q;\n \t\tpoint_len \u003d pk-\u003ekey.ec.qlen;\n@@ -292,6 +294,73 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)\n \treturn (int)glen;\n }\n \n+/*\n+ * Perform full static ECDH. This occurs only in the context of client\n+ * authentication with certificates: the server uses an EC public key,\n+ * the cipher suite is of type ECDH (not ECDHE), the server requested a\n+ * client certificate and accepts static ECDH, the client has a\n+ * certificate with an EC public key in the same curve, and accepts\n+ * static ECDH as well.\n+ *\n+ * Returned value is 0 on success, -1 on error.\n+ */\n+static int\n+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)\n+{\n+\tunsigned char point[133];\n+\tsize_t point_len;\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tpoint_len \u003d pk-\u003ekey.ec.qlen;\n+\tif (point_len \u003e sizeof point) {\n+\t\treturn -1;\n+\t}\n+\tmemcpy(point, pk-\u003ekey.ec.q, point_len);\n+\tif (!(*ctx-\u003eclient_auth_vtable)-\u003edo_keyx(\n+\t\tctx-\u003eclient_auth_vtable, point, point_len))\n+\t{\n+\t\treturn -1;\n+\t}\n+\tbr_ssl_engine_compute_master(\u0026ctx-\u003eeng,\n+\t\tprf_id, point + 1, point_len \u003e\u003e 1);\n+\treturn 0;\n+}\n+\n+/*\n+ * Compute the client-side signature. This is invoked only when a\n+ * signature-based client authentication was selected. The computed\n+ * signature is in the pad; its length (in bytes) is returned. On\n+ * error, 0 is returned.\n+ */\n+static size_t\n+make_client_sign(br_ssl_client_context *ctx)\n+{\n+\tsize_t hv_len;\n+\n+\t/*\n+\t * Compute hash of handshake messages so far. This \u0022cannot\u0022 fail\n+\t * because the list of supported hash functions provided to the\n+\t * client certificate handler was trimmed to include only the\n+\t * hash functions that the multi-hasher supports.\n+\t */\n+\tif (ctx-\u003ehash_id) {\n+\t\thv_len \u003d br_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tctx-\u003ehash_id, ctx-\u003eeng.pad);\n+\t} else {\n+\t\tbr_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tbr_md5_ID, ctx-\u003eeng.pad);\n+\t\tbr_multihash_out(\u0026ctx-\u003eeng.mhash,\n+\t\t\tbr_sha1_ID, ctx-\u003eeng.pad + 16);\n+\t\thv_len \u003d 36;\n+\t}\n+\treturn (*ctx-\u003eclient_auth_vtable)-\u003edo_sign(\n+\t\tctx-\u003eclient_auth_vtable, ctx-\u003ehash_id, hv_len,\n+\t\tctx-\u003eeng.pad, sizeof ctx-\u003eeng.pad);\n+}\n+\n }\n \n \u005c \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n@@ -303,6 +372,9 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)\n \tpostpone literal postpone ; ;\n \n addr-ctx: min_clienthello_len\n+addr-ctx: hashes\n+addr-ctx: auth_type\n+addr-ctx: hash_id\n \n \u005c Length of the Secure Renegotiation extension. This is 5 for the\n \u005c first handshake, 17 for a renegotiation (if the server supports the\n@@ -319,16 +391,6 @@ addr-ctx: min_clienthello_len\n : ext-frag-length ( -- len )\n \taddr-log_max_frag_len get8 14 \u003d if 0 else 5 then ;\n \n-\u005c Test support for RSA signatures.\n-cc: supports-rsa-sign? ( -- bool ) {\n-\tT0_PUSHi(-(CTX-\u003eirsavrfy !\u003d 0));\n-}\n-\n-\u005c Test support for ECDSA signatures.\n-cc: supports-ecdsa? ( -- bool ) {\n-\tT0_PUSHi(-(CTX-\u003eiecdsa !\u003d 0));\n-}\n-\n \u005c Length of Signatures extension.\n : ext-signatures-length ( -- len )\n \tsupported-hash-functions { x } drop\n@@ -709,80 +771,26 @@ cc: DEBUG-BLOB ( addr len -- ) {\n \tresume\n \t;\n \n-cc: x509-start-chain ( expected-key-type -- ) {\n-\tconst br_x509_class *xc;\n-\n-\txc \u003d *(ENG-\u003ex509ctx);\n-\txc-\u003estart_chain(ENG-\u003ex509ctx, T0_POP(), ENG-\u003eserver_name);\n-}\n-\n-cc: x509-start-cert ( length -- ) {\n-\tconst br_x509_class *xc;\n-\n-\txc \u003d *(ENG-\u003ex509ctx);\n-\txc-\u003estart_cert(ENG-\u003ex509ctx, T0_POP());\n-}\n-\n-cc: x509-append ( length -- ) {\n-\tconst br_x509_class *xc;\n-\tsize_t len;\n-\n-\txc \u003d *(ENG-\u003ex509ctx);\n-\tlen \u003d T0_POP();\n-\txc-\u003eappend(ENG-\u003ex509ctx, ENG-\u003epad, len);\n-}\n-\n-cc: x509-end-cert ( -- ) {\n-\tconst br_x509_class *xc;\n-\n-\txc \u003d *(ENG-\u003ex509ctx);\n-\txc-\u003eend_cert(ENG-\u003ex509ctx);\n-}\n-\n-cc: x509-end-chain ( -- err ) {\n+cc: set-server-curve ( -- ) {\n \tconst br_x509_class *xc;\n+\tconst br_x509_pkey *pk;\n \n \txc \u003d *(ENG-\u003ex509ctx);\n-\tT0_PUSH(xc-\u003eend_chain(ENG-\u003ex509ctx));\n+\tpk \u003d xc-\u003eget_pkey(ENG-\u003ex509ctx, NULL);\n+\tCTX-\u003eserver_curve \u003d\n+\t\t(pk-\u003ekey_type \u003d\u003d BR_KEYTYPE_EC) ? pk-\u003ekey.ec.curve : 0;\n }\n \n-\u005c Parse Certificate\n-: read-Certificate ( -- )\n-\t\u005c Get header, and check message type.\n-\tread-handshake-header 11 \u003d ifnot ERR_UNEXPECTED fail then\n-\n-\t\u005c Start processing the chain through the X.509 engine.\n+\u005c Read Certificate message from server.\n+: read-Certificate-from-server ( -- )\n \taddr-cipher_suite get16 expected-key-type\n-\tx509-start-chain\n-\n-\t\u005c Total chain length is a 24-bit integer.\n-\tread24 open-elt\n-\tbegin\n-\t\tdup while\n-\t\tread24 open-elt\n-\t\tdup x509-start-cert\n-\n-\t\t\u005c We read the certificate by chunks through the pad, so\n-\t\t\u005c as to use the existing reading function (read-blob)\n-\t\t\u005c that also ensures proper hashing.\n-\t\tbegin\n-\t\t\tdup while\n-\t\t\tdup 256 \u003e if 256 else dup then { len }\n-\t\t\taddr-pad len read-blob\n-\t\t\tlen x509-append\n-\t\trepeat\n-\t\tclose-elt\n-\t\tx509-end-cert\n-\trepeat\n-\n-\t\u005c We must close the chain AND the handshake message.\n-\tclose-elt\n-\tclose-elt\n+\t-1 read-Certificate\n+\tdup 0\u003c if neg fail then\n+\tdup ifnot ERR_UNEXPECTED fail then\n+\tover and \u003c\u003e if ERR_WRONG_KEY_USAGE fail then\n \n-\t\u005c Chain processing is finished; get the error code.\n-\tx509-end-chain\n-\tdup if fail then drop\n-\t;\n+\t\u005c Set server curve (used for static ECDH).\n+\tset-server-curve ;\n \n \u005c Verify signature on ECDHE point sent by the server.\n \u005c 'hash' is the hash function to use (1 to 6, or 0 for RSA with MD5+SHA-1)\n@@ -851,15 +859,166 @@ cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) {\n \n \tclose-elt ;\n \n+\u005c Client certificate: start processing of anchor names.\n+cc: anchor-dn-start-name-list ( -- ) {\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003estart_name_list(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+}\n+\n+\u005c Client certificate: start a new anchor DN (length is 16-bit).\n+cc: anchor-dn-start-name ( length -- ) {\n+\tsize_t len;\n+\n+\tlen \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003estart_name(\n+\t\t\tCTX-\u003eclient_auth_vtable, len);\n+\t}\n+}\n+\n+\u005c Client certificate: push some data for current anchor DN.\n+cc: anchor-dn-append-name ( length -- ) {\n+\tsize_t len;\n+\n+\tlen \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eappend_name(\n+\t\t\tCTX-\u003eclient_auth_vtable, ENG-\u003epad, len);\n+\t}\n+}\n+\n+\u005c Client certificate: end current anchor DN.\n+cc: anchor-dn-end-name ( -- ) {\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eend_name(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+}\n+\n+\u005c Client certificate: end list of anchor DN.\n+cc: anchor-dn-end-name-list ( -- ) {\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003eend_name_list(\n+\t\t\tCTX-\u003eclient_auth_vtable);\n+\t}\n+}\n+\n+\u005c Client certificate: obtain the client certificate chain.\n+cc: get-client-chain ( auth_types -- ) {\n+\tuint32_t auth_types;\n+\n+\tauth_types \u003d T0_POP();\n+\tif (CTX-\u003eclient_auth_vtable !\u003d NULL) {\n+\t\tbr_ssl_client_certificate ux;\n+\n+\t\t(*CTX-\u003eclient_auth_vtable)-\u003echoose(CTX-\u003eclient_auth_vtable,\n+\t\t\tCTX, auth_types, \u0026ux);\n+\t\tCTX-\u003eauth_type \u003d (unsigned char)ux.auth_type;\n+\t\tCTX-\u003ehash_id \u003d (unsigned char)ux.hash_id;\n+\t\tENG-\u003echain \u003d ux.chain;\n+\t\tENG-\u003echain_len \u003d ux.chain_len;\n+\t} else {\n+\t\tCTX-\u003ehash_id \u003d 0;\n+\t\tENG-\u003echain_len \u003d 0;\n+\t}\n+}\n+\n \u005c Parse CertificateRequest. Header has already been read.\n : read-contents-CertificateRequest ( lim -- )\n-\t\u005c TODO: implement client certificates. Right now, we simply\n-\t\u005c drop the complete message.\n-\tbegin dup while read8 drop repeat drop ;\n+\t\u005c Read supported client authentification types. We keep only\n+\t\u005c RSA, ECDSA, and ECDH.\n+\t0 { auth_types }\n+\tread8 open-elt\n+\tbegin dup while\n+\t\tread8 case\n+\t\t\t1 of 0x0000FF endof\n+\t\t\t64 of 0x00FF00 endof\n+\t\t\t65 of 0x010000 endof\n+\t\t\t66 of 0x020000 endof\n+\t\t\t0 swap\n+\t\tendcase\n+\t\tauth_types or \u003eauth_types\n+\trepeat\n+\tclose-elt\n+\n+\t\u005c Full static ECDH is allowed only if the cipher suite is ECDH\n+\t\u005c (not ECDHE). It would be theoretically feasible to use static\n+\t\u005c ECDH on the client side with an ephemeral key pair from the\n+\t\u005c server, but RFC 4492 (section 3) forbids it because ECDHE suites\n+\t\u005c are supposed to provide forward secrecy, and static ECDH would\n+\t\u005c negate that property.\n+\taddr-cipher_suite get16 use-ecdh? ifnot\n+\t\tauth_types 0xFFFF and \u003eauth_types\n+\tthen\n+\n+\t\u005c Note: if the cipher suite is ECDH, then the X.509 validation\n+\t\u005c engine was invoked with the BR_KEYTYPE_EC | BR_KEYTYPE_KEYX\n+\t\u005c combination, so the server's public key has already been\n+\t\u005c checked to be fit for a key exchange.\n+\n+\t\u005c With TLS 1.2:\n+\t\u005c - rsa_fixed_ecdh and ecdsa_fixed_ecdh are synoymous.\n+\t\u005c - There is an explicit list of supported sign+hash.\n+\t\u005c With TLS 1.0,\n+\taddr-version get16 0x0303 \u003e\u003d if\n+\t\t\u005c With TLS 1.2:\n+\t\t\u005c - There is an explicit list of supported sign+hash.\n+\t\t\u005c - The ECDH flags must be adjusted for RSA/ECDSA\n+\t\t\u005c support.\n+\t\tread-list-sign-algos dup addr-hashes set16\n+\n+\t\t\u005c Trim down the list depending on what hash functions\n+\t\t\u005c we support (since the hashing itself is done by the SSL\n+\t\t\u005c engine, not by the certificate handler).\n+\t\tsupported-hash-functions drop dup 8 \u003c\u003c or 0x030000 or and\n+\n+\t\tauth_types and\n+\t\tauth_types 0x030000 and if\n+\t\t\tdup 0x0000FF and if 0x010000 or then\n+\t\t\tdup 0x00FF00 and if 0x020000 or then\n+\t\tthen\n+\t\t\u003eauth_types\n+\telse\n+\t\t\u005c TLS 1.0 or 1.1. The hash function is fixed for signatures\n+\t\t\u005c (MD5+SHA-1 for RSA, SHA-1 for ECDSA).\n+\t\tauth_types 0x030401 and \u003eauth_types\n+\tthen\n+\n+\t\u005c Parse list of anchor DN.\n+\tanchor-dn-start-name-list\n+\tread16 open-elt\n+\tbegin dup while\n+\t\tread16 open-elt\n+\t\tdup anchor-dn-start-name\n+\n+\t\t\u005c We read the DN by chunks through the pad, so\n+\t\t\u005c as to use the existing reading function (read-blob)\n+\t\t\u005c that also ensures proper hashing.\n+\t\tbegin\n+\t\t\tdup while\n+\t\t\tdup 256 \u003e if 256 else dup then { len }\n+\t\t\taddr-pad len read-blob\n+\t\t\tlen anchor-dn-append-name\n+\t\trepeat\n+\t\tclose-elt\n+\t\tanchor-dn-end-name\n+\trepeat\n+\tclose-elt\n+\tanchor-dn-end-name-list\n+\n+\t\u005c We should have reached the message end.\n+\tclose-elt\n+\n+\t\u005c Obtain the client chain.\n+\tauth_types get-client-chain\n+\t;\n \n+\u005c (obsolete)\n \u005c Write an empty Certificate message.\n-: write-empty-Certificate ( -- )\n-\t11 write8 3 write24 0 write24 ;\n+\u005c : write-empty-Certificate ( -- )\n+\u005c \t11 write8 3 write24 0 write24 ;\n \n cc: do-rsa-encrypt ( prf_id -- nlen ) {\n \tint x;\n@@ -887,7 +1046,27 @@ cc: do-ecdh ( echde prf_id -- ulen ) {\n \t}\n }\n \n-\u005c Write ClientKeyExchange\n+cc: do-static-ecdh ( prf-id -- ) {\n+\tunsigned prf_id \u003d T0_POP();\n+\n+\tif (make_pms_static_ecdh(CTX, prf_id) \u003c 0) {\n+\t\tbr_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);\n+\t\tT0_CO();\n+\t}\n+}\n+\n+cc: do-client-sign ( -- sig_len ) {\n+\tsize_t sig_len;\n+\n+\tsig_len \u003d make_client_sign(CTX);\n+\tif (sig_len \u003d\u003d 0) {\n+\t\tbr_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);\n+\t\tT0_CO();\n+\t}\n+\tT0_PUSH(sig_len);\n+}\n+\n+\u005c Write ClientKeyExchange.\n : write-ClientKeyExchange ( -- )\n \t16 write8\n \taddr-cipher_suite get16\n@@ -903,6 +1082,20 @@ cc: do-ecdh ( echde prf_id -- ulen ) {\n \t\taddr-pad swap write-blob\n \tthen ;\n \n+\u005c Write CertificateVerify. This is invoked only if a client certificate\n+\u005c was requested and sent, and the authentication is not full static ECDH.\n+: write-CertificateVerify ( -- )\n+\tdo-client-sign\n+\t15 write8 dup\n+\taddr-version get16 0x0303 \u003e\u003d if\n+\t\t4 + write24\n+\t\taddr-hash_id get8 write8\n+\t\taddr-auth_type get8 write8\n+\telse\n+\t\t2+ write24\n+\tthen\n+\tdup write16 addr-pad swap write-blob ;\n+\n \u005c \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n \n \u005c Perform a handshake.\n@@ -924,7 +1117,9 @@ cc: do-ecdh ( echde prf_id -- ulen ) {\n \n \t\t\u005c Not a session resumption.\n \n-\t\tread-Certificate\n+\t\t\u005c Read certificate; then check key type and usages against\n+\t\t\u005c cipher suite.\n+\t\tread-Certificate-from-server\n \n \t\t\u005c Depending on cipher suite, we may now expect a\n \t\t\u005c ServerKeyExchange.\n@@ -956,12 +1151,27 @@ cc: do-ecdh ( echde prf_id -- ulen ) {\n \t\tmore-incoming-bytes? if ERR_UNEXPECTED fail then\n \n \t\tseen-CR if\n-\t\t\t\u005c TODO: client certificate support.\n-\t\t\twrite-empty-Certificate\n+\t\t\t\u005c If the server requested a client certificate, then\n+\t\t\t\u005c we must write a Certificate message (it may be\n+\t\t\t\u005c empty).\n+\t\t\twrite-Certificate\n+\n+\t\t\t\u005c If using static ECDH, then the ClientKeyExchange\n+\t\t\t\u005c is empty, and there is no CertificateVerify.\n+\t\t\t\u005c Otherwise, there is a ClientKeyExchange; there\n+\t\t\t\u005c will then be a CertificateVerify if a client chain\n+\t\t\t\u005c was indeed sent.\n+\t\t\taddr-hash_id get8 0xFF \u003d if\n+\t\t\t\tdrop\n+\t\t\t\t16 write8 0 write24\n+\t\t\t\taddr-cipher_suite get16 prf-id do-static-ecdh\n+\t\t\telse\n+\t\t\t\twrite-ClientKeyExchange\n+\t\t\t\tif write-CertificateVerify then\n+\t\t\tthen\n+\t\telse\n+\t\t\twrite-ClientKeyExchange\n \t\tthen\n-\t\twrite-ClientKeyExchange\n-\n-\t\t\u005c TODO: CertificateVerify\n \n \t\t-1 write-CCS-Finished\n \t\t-1 read-CCS-Finished\ndiff --git a/src/ssl/ssl_hs_common.t0 b/src/ssl/ssl_hs_common.t0\nindex 1eb5347..da6fc8a 100644\n--- a/src/ssl/ssl_hs_common.t0\n+++ b/src/ssl/ssl_hs_common.t0\n@@ -145,12 +145,8 @@ addr-eng: version_max\n addr-eng: suites_buf\n addr-eng: suites_num\n addr-eng: server_name\n-\u005c addr-eng: version\n-\u005c addr-eng: cipher_suite\n addr-eng: client_random\n addr-eng: server_random\n-\u005c addr-eng: session_id_len\n-\u005c addr-eng: session_id\n addr-eng: ecdhe_curve\n addr-eng: ecdhe_point\n addr-eng: ecdhe_point_len\n@@ -212,6 +208,9 @@ err: ERR_LIMIT_EXCEEDED\n err: ERR_BAD_FINISHED\n err: ERR_RESUME_MISMATCH\n err: ERR_INVALID_ALGORITHM\n+err: ERR_BAD_SIGNATURE\n+err: ERR_WRONG_KEY_USAGE\n+err: ERR_NO_CLIENT_AUTH\n \n \u005c Get supported curves (bit mask).\n cc: supported-curves ( -- x ) {\n@@ -220,6 +219,7 @@ cc: supported-curves ( -- x ) {\n }\n \n \u005c Get supported hash functions (bit mask and number).\n+\u005c Note: this (on purpose) skips MD5.\n cc: supported-hash-functions ( -- x num ) {\n \tint i;\n \tunsigned x, num;\n@@ -236,6 +236,16 @@ cc: supported-hash-functions ( -- x num ) {\n \tT0_PUSH(num);\n }\n \n+\u005c Test support for RSA signatures.\n+cc: supports-rsa-sign? ( -- bool ) {\n+\tT0_PUSHi(-(ENG-\u003eirsavrfy !\u003d 0));\n+}\n+\n+\u005c Test support for ECDSA signatures.\n+cc: supports-ecdsa? ( -- bool ) {\n+\tT0_PUSHi(-(ENG-\u003eiecdsa !\u003d 0));\n+}\n+\n \u005c (Re)initialise the multihasher.\n cc: multihash-init ( -- ) {\n \tbr_multihash_init(\u0026ENG-\u003emhash);\n@@ -1020,3 +1030,186 @@ cc: compute-Finished-inner ( from_client prf_id -- ) {\n \t22 wait-rectype-out\n \twrite-Finished\n \tflush-record ;\n+\n+\u005c Read and parse a list of supported signature algorithms (with hash\n+\u005c functions). The resulting bit field is returned.\n+: read-list-sign-algos ( lim -- lim value )\n+\t0 { hashes }\n+\tread16 open-elt\n+\tbegin dup while\n+\t\tread8 { hash } read8 { sign }\n+\t\t\u005c We keep the value if the signature is either 1 (RSA)\n+\t\t\u005c or 3 (ECDSA), and the hash is one of the SHA-* functions\n+\t\t\u005c (2 to 6, from SHA-1 to SHA-512); we reject MD5.\n+\t\thash 2 \u003e\u003d hash 6 \u003c\u003d and\n+\t\tsign 1 \u003d sign 3 \u003d or\n+\t\tand if\n+\t\t\thashes 1 sign 1- 2 \u003c\u003c hash + \u003c\u003c or \u003ehashes\n+\t\tthen\n+\trepeat\n+\tclose-elt\n+\thashes ;\n+\n+\u005c \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n+\n+\u005c Compute total chain length. This includes the individual certificate\n+\u005c headers, but not the total chain header. This also sets the cert_cur,\n+\u005c cert_len and chain_len context fields.\n+cc: total-chain-length ( -- len ) {\n+\tsize_t u;\n+\tuint32_t total;\n+\n+\ttotal \u003d 0;\n+\tfor (u \u003d 0; u \u003c ENG-\u003echain_len; u ++) {\n+\t\ttotal +\u003d 3 + (uint32_t)ENG-\u003echain[u].data_len;\n+\t}\n+\tT0_PUSH(total);\n+}\n+\n+\u005c Get length for current certificate in the chain; if the chain end was\n+\u005c reached, then this returns -1.\n+cc: begin-cert ( -- len ) {\n+\tif (ENG-\u003echain_len \u003d\u003d 0) {\n+\t\tT0_PUSHi(-1);\n+\t} else {\n+\t\tENG-\u003ecert_cur \u003d ENG-\u003echain-\u003edata;\n+\t\tENG-\u003ecert_len \u003d ENG-\u003echain-\u003edata_len;\n+\t\tENG-\u003echain ++;\n+\t\tENG-\u003echain_len --;\n+\t\tT0_PUSH(ENG-\u003ecert_len);\n+\t}\n+}\n+\n+\u005c Copy a chunk of certificate data into the pad. Returned value is the\n+\u005c chunk length, or 0 if the certificate end is reached.\n+cc: copy-cert-chunk ( -- len ) {\n+\tsize_t clen;\n+\n+\tclen \u003d ENG-\u003ecert_len;\n+\tif (clen \u003e sizeof ENG-\u003epad) {\n+\t\tclen \u003d sizeof ENG-\u003epad;\n+\t}\n+\tmemcpy(ENG-\u003epad, ENG-\u003ecert_cur, clen);\n+\tENG-\u003ecert_cur +\u003d clen;\n+\tENG-\u003ecert_len -\u003d clen;\n+\tT0_PUSH(clen);\n+}\n+\n+\u005c Write a Certificate message. Total chain length (excluding the 3-byte\n+\u005c header) is returned; it is 0 if the chain is empty.\n+: write-Certificate ( -- total_chain_len )\n+\t11 write8\n+\ttotal-chain-length dup\n+\tdup 3 + write24 write24\n+\tbegin\n+\t\tbegin-cert\n+\t\tdup 0\u003c if drop ret then write24\n+\t\tbegin copy-cert-chunk dup while\n+\t\t\taddr-pad swap write-blob\n+\t\trepeat\n+\t\tdrop\n+\tagain ;\n+\n+cc: x509-start-chain ( by_client -- ) {\n+\tconst br_x509_class *xc;\n+\tuint32_t bc;\n+\n+\tbc \u003d T0_POP();\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003estart_chain(ENG-\u003ex509ctx, bc ? ENG-\u003eserver_name : NULL);\n+}\n+\n+cc: x509-start-cert ( length -- ) {\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003estart_cert(ENG-\u003ex509ctx, T0_POP());\n+}\n+\n+cc: x509-append ( length -- ) {\n+\tconst br_x509_class *xc;\n+\tsize_t len;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tlen \u003d T0_POP();\n+\txc-\u003eappend(ENG-\u003ex509ctx, ENG-\u003epad, len);\n+}\n+\n+cc: x509-end-cert ( -- ) {\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003eend_cert(ENG-\u003ex509ctx);\n+}\n+\n+cc: x509-end-chain ( -- err ) {\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tT0_PUSH(xc-\u003eend_chain(ENG-\u003ex509ctx));\n+}\n+\n+cc: get-key-type-usages ( -- key-type-usages ) {\n+\tconst br_x509_class *xc;\n+\tconst br_x509_pkey *pk;\n+\tunsigned usages;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tpk \u003d xc-\u003eget_pkey(ENG-\u003ex509ctx, \u0026usages);\n+\tif (pk \u003d\u003d NULL) {\n+\t\tT0_PUSH(0);\n+\t} else {\n+\t\tT0_PUSH(pk-\u003ekey_type | usages);\n+\t}\n+}\n+\n+\u005c Read a Certificate message.\n+\u005c Parameter: non-zero if this is a read by the client of a certificate\n+\u005c sent by the server; zero otherwise.\n+\u005c Returned value:\n+\u005c - Empty: 0\n+\u005c - Valid: combination of key type and allowed key usages.\n+\u005c - Invalid: negative (-x for error code x)\n+: read-Certificate ( by_client -- key-type-usages )\n+\t\u005c Get header, and check message type.\n+\tread-handshake-header 11 \u003d ifnot ERR_UNEXPECTED fail then\n+\n+\t\u005c If the chain is empty, do some special processing.\n+\tdup 3 \u003d if\n+\t\tread24 if ERR_BAD_PARAM fail then\n+\t\tswap drop ret\n+\tthen\n+\n+\t\u005c Start processing the chain through the X.509 engine.\n+\tswap x509-start-chain\n+\n+\t\u005c Total chain length is a 24-bit integer.\n+\tread24 open-elt\n+\tbegin\n+\t\tdup while\n+\t\tread24 open-elt\n+\t\tdup x509-start-cert\n+\n+\t\t\u005c We read the certificate by chunks through the pad, so\n+\t\t\u005c as to use the existing reading function (read-blob)\n+\t\t\u005c that also ensures proper hashing.\n+\t\tbegin\n+\t\t\tdup while\n+\t\t\tdup 256 \u003e if 256 else dup then { len }\n+\t\t\taddr-pad len read-blob\n+\t\t\tlen x509-append\n+\t\trepeat\n+\t\tclose-elt\n+\t\tx509-end-cert\n+\trepeat\n+\n+\t\u005c We must close the chain AND the handshake message.\n+\tclose-elt\n+\tclose-elt\n+\n+\t\u005c Chain processing is finished; get the error code.\n+\tx509-end-chain\n+\tdup if neg ret then drop\n+\n+\t\u005c Return key type and usages.\n+\tget-key-type-usages ;\ndiff --git a/src/ssl/ssl_hs_server.c b/src/ssl/ssl_hs_server.c\nindex a46734d..14dcf33 100644\n--- a/src/ssl/ssl_hs_server.c\n+++ b/src/ssl/ssl_hs_server.c\n@@ -196,6 +196,35 @@ do_ecdh(br_ssl_server_context *ctx, int prf_id,\n }\n \n /*\n+ * Do the full static ECDH key exchange. When this function is called,\n+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),\n+ * and the client's public key (from its certificate) has type EC and is\n+ * apt for key exchange.\n+ */\n+static void\n+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)\n+{\n+\tunsigned char cpoint[133];\n+\tsize_t cpoint_len;\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tcpoint_len \u003d pk-\u003ekey.ec.qlen;\n+\tif (cpoint_len \u003e sizeof cpoint) {\n+\t\t/*\n+\t\t * If the point is larger than our buffer then we need to\n+\t\t * restrict it. Length 2 is not a valid point length, so\n+\t\t * the ECDH will fail.\n+\t\t */\n+\t\tcpoint_len \u003d 2;\n+\t}\n+\tmemcpy(cpoint, pk-\u003ekey.ec.q, cpoint_len);\n+\tdo_ecdh(ctx, prf_id, cpoint, cpoint_len);\n+}\n+\n+/*\n * Do the ECDHE key exchange (part 1: generation of transient key, and\n * computing of the point to send to the client). Returned value is the\n * signature length (in bytes), or -x on error (with x being an error\n@@ -313,6 +342,94 @@ do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,\n \tmemset(ctx-\u003eecdhe_key, 0, ctx-\u003eecdhe_key_len);\n }\n \n+/*\n+ * Offset for hash value within the pad (when obtaining all hash values,\n+ * in preparation for verification of the CertificateVerify message).\n+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value\n+ * is used to get the total length.\n+ */\n+static const unsigned char HASH_PAD_OFF[] \u003d { 0, 16, 36, 64, 96, 144, 208 };\n+\n+/*\n+ * OID for hash functions in RSA signatures.\n+ */\n+static const unsigned char HASH_OID_SHA1[] \u003d {\n+\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n+};\n+\n+static const unsigned char HASH_OID_SHA224[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n+};\n+\n+static const unsigned char HASH_OID_SHA256[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n+};\n+\n+static const unsigned char HASH_OID_SHA384[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n+};\n+\n+static const unsigned char HASH_OID_SHA512[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n+};\n+\n+static const unsigned char *HASH_OID[] \u003d {\n+\tHASH_OID_SHA1,\n+\tHASH_OID_SHA224,\n+\tHASH_OID_SHA256,\n+\tHASH_OID_SHA384,\n+\tHASH_OID_SHA512\n+};\n+\n+/*\n+ * Verify the signature in CertificateVerify. Returned value is 0 on\n+ * success, or a non-zero error code. Lack of implementation of the\n+ * designated signature algorithm is reported as a \u0022bad signature\u0022\n+ * error (because it means that the peer did not honour our advertised\n+ * set of supported signature algorithms).\n+ */\n+static int\n+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)\n+{\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\tint id;\n+\n+\tid \u003d ctx-\u003ehash_CV_id;\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tif (pk-\u003ekey_type \u003d\u003d BR_KEYTYPE_RSA) {\n+\t\tunsigned char tmp[64];\n+\t\tconst unsigned char *hash_oid;\n+\n+\t\tif (id \u003d\u003d 0) {\n+\t\t\thash_oid \u003d NULL;\n+\t\t} else {\n+\t\t\thash_oid \u003d HASH_OID[id - 2];\n+\t\t}\n+\t\tif (ctx-\u003eeng.irsavrfy \u003d\u003d 0) {\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t\tif (!ctx-\u003eeng.irsavrfy(ctx-\u003eeng.pad, sig_len,\n+\t\t\thash_oid, ctx-\u003ehash_CV_len, \u0026pk-\u003ekey.rsa, tmp)\n+\t\t\t|| memcmp(tmp, ctx-\u003ehash_CV, ctx-\u003ehash_CV_len) !\u003d 0)\n+\t\t{\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t} else {\n+\t\tif (ctx-\u003eeng.iecdsa \u003d\u003d 0) {\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t\tif (!ctx-\u003eeng.iecdsa(ctx-\u003eeng.iec,\n+\t\t\tctx-\u003ehash_CV, ctx-\u003ehash_CV_len,\n+\t\t\t\u0026pk-\u003ekey.ec, ctx-\u003eeng.pad, sig_len))\n+\t\t{\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n \n \n static const uint8_t t0_datablock[] \u003d {\n@@ -332,19 +449,23 @@ static const uint8_t t0_datablock[] \u003d {\n };\n \n static const uint8_t t0_codeblock[] \u003d {\n-\t0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01,\n-\t0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08,\n+\t0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01,\n+\t0x00, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x08,\n \t0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,\n-\t0x21, 0x21, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00,\n+\t0x28, 0x28, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00,\n \t0x01, T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01,\n+\tT0_INT1(BR_ERR_BAD_SIGNATURE), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01,\n-\tT0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),\n+\tT0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01,\n+\tT0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,\n+\tT0_INT1(BR_ERR_NO_CLIENT_AUTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),\n \t0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,\n+\tT0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,\n@@ -363,7 +484,7 @@ static const uint8_t t0_codeblock[] \u003d {\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)),\n \t0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)),\n \t0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)),\n-\t0x00, 0x00, 0x5D, 0x01,\n+\t0x00, 0x00, 0x73, 0x01,\n \tT0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),\n \t0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00,\n@@ -393,203 +514,257 @@ static const uint8_t t0_codeblock[] \u003d {\n \tT0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,\n \t0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),\n-\t0x00, 0x00, 0x09, 0x22, 0x44, 0x06, 0x02, 0x50, 0x23, 0x00, 0x00, 0x01,\n-\t0x01, 0x00, 0x01, 0x03, 0x00, 0x7B, 0x22, 0x4A, 0x3B, 0x7F, 0x22, 0x05,\n-\t0x04, 0x4B, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0x7F, 0x00,\n-\t0x4A, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x50, 0x23, 0x00, 0x00, 0x22, 0x6C,\n-\t0x3B, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x3B, 0x5A, 0x25, 0x81, 0x07, 0x19,\n-\t0x67, 0x01, 0x0C, 0x2A, 0x00, 0x00, 0x22, 0x1B, 0x01, 0x08, 0x0B, 0x3B,\n-\t0x48, 0x1B, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, 0x59, 0x38, 0x24,\n-\t0x16, 0x2F, 0x06, 0x08, 0x02, 0x00, 0x81, 0x26, 0x03, 0x00, 0x04, 0x74,\n-\t0x01, 0x00, 0x81, 0x1E, 0x02, 0x00, 0x22, 0x16, 0x12, 0x06, 0x02, 0x54,\n-\t0x23, 0x81, 0x26, 0x04, 0x75, 0x00, 0x01, 0x00, 0x59, 0x38, 0x01, 0x16,\n-\t0x6A, 0x38, 0x2D, 0x81, 0x0B, 0x2C, 0x06, 0x02, 0x56, 0x23, 0x06, 0x0C,\n-\t0x81, 0x2C, 0x01, 0x00, 0x81, 0x29, 0x01, 0x00, 0x81, 0x0A, 0x04, 0x14,\n-\t0x81, 0x2C, 0x81, 0x2A, 0x81, 0x2E, 0x81, 0x2D, 0x24, 0x81, 0x0C, 0x01,\n-\t0x00, 0x81, 0x0A, 0x01, 0x00, 0x81, 0x29, 0x34, 0x01, 0x01, 0x59, 0x38,\n-\t0x01, 0x17, 0x6A, 0x38, 0x00, 0x00, 0x31, 0x31, 0x00, 0x01, 0x03, 0x00,\n-\t0x24, 0x16, 0x2F, 0x06, 0x05, 0x81, 0x25, 0x21, 0x04, 0x77, 0x01, 0x02,\n-\t0x02, 0x00, 0x81, 0x1D, 0x16, 0x2F, 0x06, 0x05, 0x81, 0x25, 0x21, 0x04,\n-\t0x77, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x23, 0x00, 0x00, 0x63, 0x26,\n-\t0x3B, 0x11, 0x01, 0x01, 0x12, 0x2E, 0x00, 0x00, 0x01, 0x7F, 0x81, 0x01,\n-\t0x81, 0x25, 0x22, 0x01, 0x07, 0x12, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x0A,\n-\t0x21, 0x01, 0x10, 0x12, 0x06, 0x02, 0x81, 0x1C, 0x04, 0x2E, 0x01, 0x01,\n-\t0x31, 0x0E, 0x06, 0x25, 0x21, 0x21, 0x6B, 0x27, 0x01, 0x01, 0x0E, 0x01,\n-\t0x01, 0x81, 0x04, 0x30, 0x06, 0x11, 0x24, 0x16, 0x2F, 0x06, 0x05, 0x81,\n-\t0x25, 0x21, 0x04, 0x77, 0x01, 0x80, 0x64, 0x81, 0x1E, 0x04, 0x04, 0x01,\n-\t0x00, 0x81, 0x01, 0x04, 0x03, 0x56, 0x23, 0x21, 0x04, 0xFF, 0x39, 0x01,\n-\t0x22, 0x03, 0x00, 0x09, 0x22, 0x44, 0x06, 0x02, 0x50, 0x23, 0x02, 0x00,\n-\t0x00, 0x00, 0x7C, 0x01, 0x0F, 0x12, 0x00, 0x00, 0x58, 0x27, 0x01, 0x00,\n-\t0x31, 0x0E, 0x06, 0x10, 0x21, 0x22, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x21,\n-\t0x01, 0x02, 0x58, 0x38, 0x01, 0x00, 0x04, 0x22, 0x01, 0x01, 0x31, 0x0E,\n-\t0x06, 0x15, 0x21, 0x01, 0x00, 0x58, 0x38, 0x22, 0x01, 0x80, 0x64, 0x0E,\n-\t0x06, 0x05, 0x01, 0x82, 0x00, 0x08, 0x23, 0x46, 0x00, 0x04, 0x07, 0x21,\n-\t0x01, 0x82, 0x00, 0x08, 0x23, 0x21, 0x00, 0x00, 0x01, 0x00, 0x28, 0x06,\n-\t0x06, 0x33, 0x81, 0x08, 0x30, 0x04, 0x77, 0x22, 0x06, 0x04, 0x01, 0x01,\n-\t0x71, 0x38, 0x00, 0x00, 0x28, 0x06, 0x0B, 0x69, 0x27, 0x01, 0x14, 0x0D,\n-\t0x06, 0x02, 0x56, 0x23, 0x04, 0x12, 0x81, 0x25, 0x01, 0x07, 0x12, 0x22,\n-\t0x01, 0x02, 0x0D, 0x06, 0x06, 0x06, 0x02, 0x56, 0x23, 0x04, 0x6F, 0x21,\n-\t0x81, 0x1A, 0x01, 0x01, 0x0D, 0x2C, 0x30, 0x06, 0x02, 0x4C, 0x23, 0x22,\n-\t0x01, 0x01, 0x81, 0x20, 0x2F, 0x81, 0x0D, 0x00, 0x0A, 0x81, 0x12, 0x01,\n-\t0x01, 0x0E, 0x05, 0x02, 0x56, 0x23, 0x81, 0x17, 0x22, 0x03, 0x00, 0x5B,\n-\t0x36, 0x5C, 0x01, 0x20, 0x81, 0x0E, 0x81, 0x19, 0x22, 0x01, 0x20, 0x0F,\n-\t0x06, 0x02, 0x55, 0x23, 0x22, 0x70, 0x38, 0x6F, 0x3B, 0x81, 0x0E, 0x17,\n-\t0x03, 0x01, 0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x03, 0x02, 0x01, 0x00,\n-\t0x03, 0x03, 0x65, 0x81, 0x02, 0x14, 0x31, 0x08, 0x03, 0x04, 0x03, 0x05,\n-\t0x22, 0x06, 0x80, 0x70, 0x81, 0x17, 0x22, 0x03, 0x06, 0x02, 0x01, 0x06,\n-\t0x0A, 0x22, 0x5A, 0x25, 0x0E, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x03, 0x22,\n-\t0x01, 0x81, 0x7F, 0x0E, 0x06, 0x0A, 0x6B, 0x27, 0x06, 0x02, 0x51, 0x23,\n-\t0x01, 0x7F, 0x03, 0x02, 0x22, 0x01, 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x11,\n-\t0x02, 0x00, 0x78, 0x25, 0x10, 0x02, 0x00, 0x77, 0x25, 0x0A, 0x12, 0x06,\n-\t0x04, 0x01, 0x7F, 0x03, 0x00, 0x81, 0x1B, 0x22, 0x44, 0x06, 0x03, 0x21,\n-\t0x04, 0x27, 0x01, 0x00, 0x81, 0x04, 0x06, 0x0B, 0x01, 0x02, 0x0B, 0x5D,\n-\t0x08, 0x02, 0x06, 0x3B, 0x36, 0x04, 0x16, 0x21, 0x02, 0x05, 0x02, 0x04,\n-\t0x10, 0x06, 0x02, 0x4F, 0x23, 0x02, 0x06, 0x02, 0x05, 0x36, 0x02, 0x05,\n-\t0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x0C, 0x21, 0x01, 0x00, 0x03,\n-\t0x07, 0x81, 0x19, 0x81, 0x06, 0x22, 0x06, 0x0A, 0x81, 0x19, 0x05, 0x04,\n-\t0x01, 0x7F, 0x03, 0x07, 0x04, 0x73, 0x7D, 0x01, 0x00, 0x6D, 0x38, 0x01,\n-\t0x88, 0x04, 0x64, 0x36, 0x01, 0x84, 0x80, 0x80, 0x00, 0x60, 0x37, 0x22,\n-\t0x06, 0x80, 0x4D, 0x81, 0x17, 0x81, 0x06, 0x22, 0x06, 0x80, 0x44, 0x81,\n-\t0x17, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x11, 0x04, 0x34,\n-\t0x01, 0x01, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x0F, 0x04, 0x29, 0x01,\n-\t0x83, 0xFE, 0x01, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x10, 0x04, 0x1C,\n-\t0x01, 0x0D, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x15, 0x04, 0x11, 0x01,\n-\t0x0A, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x16, 0x04, 0x06, 0x21, 0x81,\n-\t0x14, 0x01, 0x00, 0x21, 0x04, 0xFF, 0x38, 0x7D, 0x7D, 0x02, 0x01, 0x02,\n-\t0x03, 0x12, 0x03, 0x01, 0x02, 0x00, 0x44, 0x06, 0x09, 0x5B, 0x25, 0x79,\n-\t0x36, 0x01, 0x80, 0x56, 0x81, 0x03, 0x77, 0x25, 0x22, 0x02, 0x00, 0x0F,\n-\t0x06, 0x03, 0x21, 0x02, 0x00, 0x22, 0x01, 0x86, 0x00, 0x0A, 0x06, 0x02,\n-\t0x52, 0x23, 0x02, 0x00, 0x78, 0x25, 0x0A, 0x06, 0x05, 0x01, 0x80, 0x46,\n-\t0x81, 0x03, 0x02, 0x01, 0x06, 0x10, 0x75, 0x25, 0x02, 0x00, 0x0C, 0x06,\n-\t0x05, 0x21, 0x75, 0x25, 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x22, 0x75,\n-\t0x36, 0x22, 0x76, 0x36, 0x22, 0x79, 0x36, 0x01, 0x86, 0x03, 0x10, 0x03,\n-\t0x08, 0x02, 0x02, 0x06, 0x04, 0x01, 0x02, 0x6B, 0x38, 0x02, 0x07, 0x05,\n-\t0x04, 0x01, 0x28, 0x81, 0x03, 0x3A, 0x21, 0x01, 0x82, 0x01, 0x07, 0x64,\n-\t0x25, 0x12, 0x22, 0x64, 0x36, 0x45, 0x03, 0x09, 0x60, 0x26, 0x39, 0x12,\n-\t0x22, 0x60, 0x37, 0x05, 0x04, 0x01, 0x00, 0x03, 0x09, 0x02, 0x01, 0x06,\n-\t0x03, 0x01, 0x7F, 0x00, 0x6F, 0x01, 0x20, 0x2B, 0x01, 0x20, 0x70, 0x38,\n-\t0x5D, 0x22, 0x03, 0x05, 0x22, 0x02, 0x04, 0x0A, 0x06, 0x80, 0x47, 0x22,\n-\t0x25, 0x22, 0x7C, 0x02, 0x09, 0x05, 0x13, 0x22, 0x01, 0x0C, 0x11, 0x22,\n-\t0x01, 0x01, 0x0E, 0x3B, 0x01, 0x02, 0x0E, 0x30, 0x06, 0x04, 0x4B, 0x01,\n-\t0x00, 0x22, 0x02, 0x08, 0x05, 0x0E, 0x22, 0x01, 0x81, 0x70, 0x12, 0x01,\n-\t0x20, 0x0D, 0x06, 0x04, 0x4B, 0x01, 0x00, 0x22, 0x22, 0x06, 0x10, 0x02,\n-\t0x05, 0x4A, 0x36, 0x02, 0x05, 0x36, 0x02, 0x05, 0x01, 0x04, 0x08, 0x03,\n-\t0x05, 0x04, 0x01, 0x4B, 0x01, 0x04, 0x08, 0x04, 0xFF, 0x32, 0x21, 0x02,\n-\t0x05, 0x5D, 0x09, 0x01, 0x02, 0x11, 0x22, 0x05, 0x04, 0x01, 0x28, 0x81,\n-\t0x03, 0x5E, 0x38, 0x15, 0x05, 0x04, 0x01, 0x28, 0x81, 0x03, 0x01, 0x00,\n-\t0x00, 0x04, 0x81, 0x12, 0x01, 0x10, 0x0E, 0x05, 0x02, 0x56, 0x23, 0x5A,\n-\t0x25, 0x81, 0x24, 0x06, 0x19, 0x81, 0x17, 0x22, 0x01, 0x84, 0x00, 0x0F,\n-\t0x06, 0x02, 0x53, 0x23, 0x22, 0x03, 0x00, 0x67, 0x3B, 0x81, 0x0E, 0x02,\n-\t0x00, 0x5A, 0x25, 0x81, 0x07, 0x20, 0x5A, 0x25, 0x22, 0x81, 0x22, 0x3B,\n-\t0x81, 0x21, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x30, 0x06,\n-\t0x17, 0x81, 0x19, 0x22, 0x03, 0x03, 0x67, 0x3B, 0x81, 0x0E, 0x02, 0x03,\n-\t0x5A, 0x25, 0x81, 0x07, 0x02, 0x02, 0x06, 0x03, 0x1F, 0x04, 0x01, 0x1D,\n-\t0x7D, 0x00, 0x00, 0x7E, 0x81, 0x12, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x56,\n-\t0x23, 0x67, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x0E, 0x7D, 0x67, 0x22,\n-\t0x01, 0x0C, 0x08, 0x01, 0x0C, 0x29, 0x05, 0x02, 0x4D, 0x23, 0x00, 0x02,\n-\t0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x7A, 0x02, 0x01, 0x02, 0x00, 0x32,\n-\t0x22, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x4B, 0x00, 0x81, 0x27, 0x04, 0x73,\n-\t0x00, 0x81, 0x17, 0x01, 0x01, 0x0D, 0x06, 0x02, 0x4E, 0x23, 0x81, 0x19,\n-\t0x22, 0x22, 0x46, 0x3B, 0x01, 0x05, 0x10, 0x30, 0x06, 0x02, 0x4E, 0x23,\n-\t0x01, 0x08, 0x08, 0x22, 0x66, 0x27, 0x0A, 0x06, 0x0D, 0x22, 0x01, 0x01,\n-\t0x3B, 0x0B, 0x35, 0x22, 0x66, 0x38, 0x68, 0x38, 0x04, 0x01, 0x21, 0x00,\n-\t0x00, 0x81, 0x17, 0x6B, 0x27, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x14, 0x21,\n-\t0x01, 0x01, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x81, 0x19, 0x06, 0x02, 0x51,\n-\t0x23, 0x01, 0x02, 0x6B, 0x38, 0x04, 0x2A, 0x01, 0x02, 0x31, 0x0E, 0x06,\n-\t0x21, 0x21, 0x01, 0x0D, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x81, 0x19, 0x01,\n-\t0x0C, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x67, 0x01, 0x0C, 0x81, 0x0E, 0x6C,\n-\t0x67, 0x01, 0x0C, 0x29, 0x05, 0x02, 0x51, 0x23, 0x04, 0x03, 0x51, 0x23,\n-\t0x21, 0x00, 0x00, 0x81, 0x17, 0x81, 0x06, 0x81, 0x17, 0x81, 0x06, 0x22,\n-\t0x06, 0x22, 0x81, 0x19, 0x06, 0x04, 0x81, 0x14, 0x04, 0x18, 0x81, 0x17,\n-\t0x22, 0x01, 0x81, 0x7F, 0x0C, 0x06, 0x0D, 0x22, 0x6D, 0x08, 0x01, 0x00,\n-\t0x3B, 0x38, 0x6D, 0x3B, 0x81, 0x0E, 0x04, 0x02, 0x81, 0x1F, 0x04, 0x5B,\n-\t0x7D, 0x7D, 0x00, 0x00, 0x81, 0x13, 0x22, 0x46, 0x06, 0x07, 0x21, 0x06,\n-\t0x02, 0x4F, 0x23, 0x04, 0x73, 0x00, 0x00, 0x81, 0x1A, 0x01, 0x03, 0x81,\n-\t0x18, 0x3B, 0x21, 0x3B, 0x00, 0x00, 0x81, 0x17, 0x81, 0x1F, 0x00, 0x02,\n-\t0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x64, 0x36, 0x81, 0x17, 0x81, 0x06,\n-\t0x22, 0x06, 0x34, 0x81, 0x19, 0x03, 0x00, 0x81, 0x19, 0x03, 0x01, 0x02,\n-\t0x00, 0x01, 0x02, 0x10, 0x02, 0x00, 0x01, 0x06, 0x0C, 0x12, 0x02, 0x01,\n-\t0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x03, 0x0E, 0x30, 0x12, 0x06, 0x11,\n-\t0x64, 0x25, 0x01, 0x01, 0x02, 0x01, 0x49, 0x01, 0x02, 0x0B, 0x02, 0x00,\n-\t0x08, 0x0B, 0x30, 0x64, 0x36, 0x04, 0x49, 0x7D, 0x7D, 0x00, 0x00, 0x81,\n-\t0x17, 0x81, 0x06, 0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x60, 0x37, 0x22,\n-\t0x06, 0x16, 0x81, 0x17, 0x22, 0x01, 0x20, 0x0A, 0x06, 0x0B, 0x01, 0x01,\n-\t0x3B, 0x0B, 0x60, 0x26, 0x30, 0x60, 0x37, 0x04, 0x01, 0x21, 0x04, 0x67,\n-\t0x7D, 0x7D, 0x00, 0x00, 0x01, 0x02, 0x7A, 0x81, 0x1A, 0x01, 0x08, 0x0B,\n-\t0x81, 0x1A, 0x08, 0x00, 0x00, 0x01, 0x03, 0x7A, 0x81, 0x1A, 0x01, 0x08,\n-\t0x0B, 0x81, 0x1A, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x1A, 0x08, 0x00, 0x00,\n-\t0x01, 0x01, 0x7A, 0x81, 0x1A, 0x00, 0x00, 0x33, 0x22, 0x44, 0x05, 0x01,\n-\t0x00, 0x21, 0x81, 0x27, 0x04, 0x75, 0x02, 0x03, 0x00, 0x74, 0x27, 0x03,\n-\t0x01, 0x01, 0x00, 0x22, 0x02, 0x01, 0x0A, 0x06, 0x10, 0x22, 0x01, 0x01,\n-\t0x0B, 0x73, 0x08, 0x25, 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00, 0x48, 0x04,\n-\t0x6A, 0x21, 0x01, 0x7F, 0x00, 0x00, 0x24, 0x16, 0x2F, 0x06, 0x05, 0x81,\n-\t0x25, 0x21, 0x04, 0x77, 0x01, 0x16, 0x6A, 0x38, 0x01, 0x00, 0x81, 0x33,\n-\t0x01, 0x00, 0x81, 0x32, 0x24, 0x01, 0x17, 0x6A, 0x38, 0x00, 0x00, 0x01,\n-\t0x15, 0x6A, 0x38, 0x3B, 0x43, 0x21, 0x43, 0x21, 0x24, 0x00, 0x00, 0x01,\n-\t0x01, 0x3B, 0x81, 0x1D, 0x00, 0x00, 0x3B, 0x31, 0x7A, 0x3B, 0x22, 0x06,\n-\t0x06, 0x81, 0x1A, 0x21, 0x49, 0x04, 0x77, 0x21, 0x00, 0x02, 0x03, 0x00,\n-\t0x5A, 0x25, 0x7C, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x12, 0x02, 0x01,\n-\t0x01, 0x04, 0x11, 0x01, 0x0F, 0x12, 0x02, 0x01, 0x01, 0x08, 0x11, 0x01,\n-\t0x0F, 0x12, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x10, 0x21, 0x01, 0x00, 0x01,\n-\t0x18, 0x02, 0x00, 0x06, 0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x80, 0x56,\n-\t0x01, 0x01, 0x31, 0x0E, 0x06, 0x10, 0x21, 0x01, 0x01, 0x01, 0x10, 0x02,\n-\t0x00, 0x06, 0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x80, 0x40, 0x01, 0x02,\n-\t0x31, 0x0E, 0x06, 0x0F, 0x21, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, 0x06,\n-\t0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x2B, 0x01, 0x03, 0x31, 0x0E, 0x06,\n-\t0x0E, 0x21, 0x21, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x3C, 0x04, 0x01,\n-\t0x3D, 0x04, 0x17, 0x01, 0x04, 0x31, 0x0E, 0x06, 0x0E, 0x21, 0x21, 0x01,\n-\t0x20, 0x02, 0x00, 0x06, 0x03, 0x3C, 0x04, 0x01, 0x3D, 0x04, 0x03, 0x50,\n-\t0x23, 0x21, 0x00, 0x00, 0x7C, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00,\n-\t0x00, 0x7C, 0x01, 0x0C, 0x11, 0x22, 0x47, 0x3B, 0x01, 0x03, 0x0A, 0x12,\n-\t0x00, 0x00, 0x7C, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x7C,\n-\t0x01, 0x0C, 0x11, 0x46, 0x00, 0x00, 0x18, 0x01, 0x00, 0x57, 0x27, 0x22,\n-\t0x06, 0x20, 0x01, 0x01, 0x31, 0x0E, 0x06, 0x07, 0x21, 0x01, 0x00, 0x81,\n-\t0x00, 0x04, 0x11, 0x01, 0x02, 0x31, 0x0E, 0x06, 0x0A, 0x21, 0x59, 0x27,\n-\t0x06, 0x03, 0x01, 0x10, 0x30, 0x04, 0x01, 0x21, 0x04, 0x01, 0x21, 0x5F,\n-\t0x27, 0x05, 0x35, 0x28, 0x06, 0x32, 0x69, 0x27, 0x01, 0x14, 0x31, 0x0E,\n-\t0x06, 0x06, 0x21, 0x01, 0x02, 0x30, 0x04, 0x24, 0x01, 0x15, 0x31, 0x0E,\n-\t0x06, 0x0B, 0x21, 0x81, 0x09, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x00, 0x04,\n-\t0x13, 0x01, 0x16, 0x31, 0x0E, 0x06, 0x06, 0x21, 0x01, 0x01, 0x30, 0x04,\n-\t0x07, 0x21, 0x01, 0x04, 0x30, 0x01, 0x00, 0x21, 0x16, 0x06, 0x03, 0x01,\n-\t0x08, 0x30, 0x00, 0x00, 0x18, 0x22, 0x05, 0x10, 0x28, 0x06, 0x0D, 0x69,\n-\t0x27, 0x01, 0x15, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x09, 0x04, 0x01, 0x1C,\n-\t0x00, 0x00, 0x81, 0x25, 0x01, 0x07, 0x12, 0x01, 0x01, 0x0F, 0x06, 0x02,\n-\t0x56, 0x23, 0x00, 0x01, 0x03, 0x00, 0x24, 0x16, 0x06, 0x05, 0x02, 0x00,\n-\t0x6A, 0x38, 0x00, 0x81, 0x25, 0x21, 0x04, 0x73, 0x00, 0x01, 0x14, 0x81,\n-\t0x28, 0x01, 0x01, 0x81, 0x33, 0x24, 0x22, 0x01, 0x00, 0x81, 0x20, 0x01,\n-\t0x16, 0x81, 0x28, 0x81, 0x2B, 0x24, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x33,\n-\t0x40, 0x22, 0x01, 0x03, 0x08, 0x81, 0x32, 0x81, 0x32, 0x13, 0x22, 0x44,\n-\t0x06, 0x02, 0x21, 0x00, 0x81, 0x32, 0x1A, 0x22, 0x06, 0x06, 0x67, 0x3B,\n-\t0x81, 0x2F, 0x04, 0x76, 0x21, 0x04, 0x6A, 0x00, 0x7E, 0x01, 0x14, 0x81,\n-\t0x33, 0x01, 0x0C, 0x81, 0x32, 0x67, 0x01, 0x0C, 0x81, 0x2F, 0x00, 0x03,\n-\t0x03, 0x00, 0x01, 0x02, 0x81, 0x33, 0x01, 0x80, 0x46, 0x6B, 0x27, 0x01,\n-\t0x02, 0x0E, 0x06, 0x0C, 0x02, 0x00, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02,\n-\t0x01, 0x1D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x01, 0x68, 0x27, 0x06, 0x04,\n-\t0x01, 0x05, 0x04, 0x02, 0x01, 0x00, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02,\n-\t0x08, 0x22, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08, 0x81, 0x32, 0x75, 0x25,\n-\t0x81, 0x31, 0x6E, 0x01, 0x04, 0x14, 0x6E, 0x01, 0x04, 0x08, 0x01, 0x1C,\n-\t0x2B, 0x6E, 0x01, 0x20, 0x81, 0x2F, 0x01, 0x20, 0x81, 0x33, 0x6F, 0x01,\n-\t0x20, 0x81, 0x2F, 0x5A, 0x25, 0x81, 0x31, 0x01, 0x00, 0x81, 0x33, 0x02,\n-\t0x01, 0x02, 0x02, 0x08, 0x22, 0x06, 0x30, 0x81, 0x31, 0x02, 0x01, 0x22,\n-\t0x06, 0x13, 0x01, 0x83, 0xFE, 0x01, 0x81, 0x31, 0x01, 0x04, 0x09, 0x22,\n-\t0x81, 0x31, 0x49, 0x6C, 0x3B, 0x81, 0x30, 0x04, 0x01, 0x21, 0x02, 0x02,\n-\t0x06, 0x0F, 0x01, 0x01, 0x81, 0x31, 0x01, 0x01, 0x81, 0x31, 0x68, 0x27,\n-\t0x01, 0x08, 0x09, 0x81, 0x33, 0x04, 0x01, 0x21, 0x00, 0x00, 0x01, 0x0E,\n-\t0x81, 0x33, 0x01, 0x00, 0x81, 0x32, 0x00, 0x03, 0x5A, 0x25, 0x81, 0x22,\n-\t0x05, 0x01, 0x00, 0x60, 0x26, 0x01, 0x00, 0x81, 0x02, 0x11, 0x01, 0x01,\n-\t0x12, 0x46, 0x06, 0x03, 0x48, 0x04, 0x74, 0x03, 0x00, 0x21, 0x02, 0x00,\n-\t0x1E, 0x22, 0x44, 0x06, 0x02, 0x2E, 0x23, 0x03, 0x01, 0x75, 0x25, 0x01,\n-\t0x86, 0x03, 0x10, 0x03, 0x02, 0x01, 0x0C, 0x81, 0x33, 0x02, 0x01, 0x62,\n-\t0x27, 0x08, 0x02, 0x02, 0x01, 0x02, 0x12, 0x08, 0x01, 0x06, 0x08, 0x81,\n-\t0x32, 0x01, 0x03, 0x81, 0x33, 0x02, 0x00, 0x81, 0x31, 0x61, 0x62, 0x27,\n-\t0x81, 0x30, 0x02, 0x02, 0x06, 0x10, 0x72, 0x27, 0x81, 0x33, 0x5A, 0x25,\n-\t0x81, 0x23, 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x81, 0x33, 0x02, 0x01,\n-\t0x81, 0x31, 0x67, 0x02, 0x01, 0x81, 0x2F, 0x00, 0x00, 0x42, 0x22, 0x01,\n-\t0x00, 0x0E, 0x06, 0x02, 0x4B, 0x00, 0x81, 0x25, 0x21, 0x04, 0x72, 0x00,\n-\t0x22, 0x81, 0x33, 0x81, 0x2F, 0x00, 0x00, 0x22, 0x01, 0x08, 0x41, 0x81,\n-\t0x33, 0x81, 0x33, 0x00, 0x00, 0x22, 0x01, 0x10, 0x41, 0x81, 0x33, 0x81,\n-\t0x31, 0x00, 0x00, 0x22, 0x43, 0x06, 0x02, 0x21, 0x00, 0x81, 0x25, 0x21,\n-\t0x04, 0x75\n+\t0x00, 0x00, 0x09, 0x29, 0x56, 0x06, 0x02, 0x62, 0x2A, 0x00, 0x00, 0x01,\n+\t0x01, 0x00, 0x01, 0x03, 0x00, 0x81, 0x11, 0x29, 0x5C, 0x46, 0x81, 0x15,\n+\t0x29, 0x05, 0x04, 0x5D, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0F, 0x06, 0x03,\n+\t0x81, 0x15, 0x00, 0x5C, 0x04, 0x69, 0x00, 0x06, 0x02, 0x62, 0x2A, 0x00,\n+\t0x00, 0x29, 0x81, 0x02, 0x46, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x46, 0x70,\n+\t0x2D, 0x81, 0x1D, 0x1C, 0x7D, 0x01, 0x0C, 0x32, 0x00, 0x00, 0x29, 0x21,\n+\t0x01, 0x08, 0x0C, 0x46, 0x5A, 0x21, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01,\n+\t0x00, 0x6F, 0x41, 0x2B, 0x19, 0x37, 0x06, 0x08, 0x02, 0x00, 0x81, 0x43,\n+\t0x03, 0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x3B, 0x02, 0x00, 0x29, 0x19,\n+\t0x13, 0x06, 0x02, 0x69, 0x2A, 0x81, 0x43, 0x04, 0x75, 0x00, 0x01, 0x00,\n+\t0x6F, 0x41, 0x01, 0x16, 0x81, 0x00, 0x41, 0x35, 0x81, 0x25, 0x34, 0x06,\n+\t0x02, 0x6B, 0x2A, 0x06, 0x0D, 0x81, 0x4A, 0x01, 0x00, 0x81, 0x46, 0x01,\n+\t0x00, 0x81, 0x21, 0x04, 0x80, 0x59, 0x81, 0x4A, 0x81, 0x47, 0x28, 0x81,\n+\t0x4C, 0x4B, 0x06, 0x02, 0x81, 0x48, 0x81, 0x4B, 0x2B, 0x4B, 0x06, 0x3C,\n+\t0x01, 0x00, 0x81, 0x22, 0x29, 0x56, 0x06, 0x13, 0x01, 0x02, 0x81, 0x1A,\n+\t0x05, 0x02, 0x36, 0x2A, 0x28, 0x81, 0x26, 0x81, 0x24, 0x29, 0x81, 0x3C,\n+\t0x28, 0x04, 0x1F, 0x29, 0x58, 0x06, 0x0D, 0x28, 0x01, 0x02, 0x81, 0x1A,\n+\t0x05, 0x02, 0x68, 0x2A, 0x81, 0x26, 0x04, 0x0E, 0x81, 0x28, 0x29, 0x05,\n+\t0x05, 0x28, 0x81, 0x20, 0x04, 0x04, 0x81, 0x27, 0x81, 0x23, 0x04, 0x02,\n+\t0x81, 0x26, 0x01, 0x00, 0x81, 0x21, 0x01, 0x00, 0x81, 0x46, 0x3D, 0x01,\n+\t0x01, 0x6F, 0x41, 0x01, 0x17, 0x81, 0x00, 0x41, 0x00, 0x00, 0x39, 0x39,\n+\t0x00, 0x01, 0x03, 0x00, 0x2B, 0x19, 0x37, 0x06, 0x05, 0x81, 0x42, 0x28,\n+\t0x04, 0x77, 0x01, 0x02, 0x02, 0x00, 0x81, 0x3A, 0x19, 0x37, 0x06, 0x05,\n+\t0x81, 0x42, 0x28, 0x04, 0x77, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x2A,\n+\t0x00, 0x00, 0x79, 0x2E, 0x46, 0x12, 0x01, 0x01, 0x13, 0x36, 0x00, 0x00,\n+\t0x01, 0x7F, 0x81, 0x17, 0x81, 0x42, 0x29, 0x01, 0x07, 0x13, 0x01, 0x00,\n+\t0x39, 0x0F, 0x06, 0x0A, 0x28, 0x01, 0x10, 0x13, 0x06, 0x02, 0x81, 0x39,\n+\t0x04, 0x2F, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x26, 0x28, 0x28, 0x81, 0x01,\n+\t0x2F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x81, 0x1A, 0x38, 0x06, 0x11, 0x2B,\n+\t0x19, 0x37, 0x06, 0x05, 0x81, 0x42, 0x28, 0x04, 0x77, 0x01, 0x80, 0x64,\n+\t0x81, 0x3B, 0x04, 0x04, 0x01, 0x00, 0x81, 0x17, 0x04, 0x03, 0x6B, 0x2A,\n+\t0x28, 0x04, 0xFF, 0x38, 0x01, 0x29, 0x03, 0x00, 0x09, 0x29, 0x56, 0x06,\n+\t0x02, 0x62, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0F, 0x13,\n+\t0x00, 0x00, 0x6E, 0x2F, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x10, 0x28, 0x29,\n+\t0x01, 0x01, 0x0E, 0x06, 0x03, 0x28, 0x01, 0x02, 0x6E, 0x41, 0x01, 0x00,\n+\t0x04, 0x22, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x15, 0x28, 0x01, 0x00, 0x6E,\n+\t0x41, 0x29, 0x01, 0x80, 0x64, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x08,\n+\t0x2A, 0x58, 0x00, 0x04, 0x07, 0x28, 0x01, 0x82, 0x00, 0x08, 0x2A, 0x28,\n+\t0x00, 0x00, 0x01, 0x00, 0x30, 0x06, 0x06, 0x3C, 0x81, 0x1E, 0x38, 0x04,\n+\t0x77, 0x29, 0x06, 0x05, 0x01, 0x01, 0x81, 0x07, 0x41, 0x00, 0x00, 0x01,\n+\t0x1F, 0x13, 0x01, 0x12, 0x0F, 0x05, 0x02, 0x6C, 0x2A, 0x70, 0x2D, 0x29,\n+\t0x81, 0x3E, 0x05, 0x02, 0x6B, 0x2A, 0x81, 0x1D, 0x27, 0x00, 0x00, 0x30,\n+\t0x06, 0x0B, 0x7F, 0x2F, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x6B, 0x2A, 0x04,\n+\t0x12, 0x81, 0x42, 0x01, 0x07, 0x13, 0x29, 0x01, 0x02, 0x0E, 0x06, 0x06,\n+\t0x06, 0x02, 0x6B, 0x2A, 0x04, 0x6F, 0x28, 0x81, 0x37, 0x01, 0x01, 0x0E,\n+\t0x34, 0x38, 0x06, 0x02, 0x5E, 0x2A, 0x29, 0x01, 0x01, 0x81, 0x3D, 0x37,\n+\t0x81, 0x29, 0x00, 0x01, 0x81, 0x2E, 0x01, 0x0B, 0x0F, 0x05, 0x02, 0x6B,\n+\t0x2A, 0x29, 0x01, 0x03, 0x0F, 0x06, 0x09, 0x81, 0x35, 0x06, 0x02, 0x62,\n+\t0x2A, 0x46, 0x28, 0x00, 0x46, 0x55, 0x81, 0x35, 0x81, 0x1C, 0x29, 0x06,\n+\t0x27, 0x81, 0x35, 0x81, 0x1C, 0x29, 0x54, 0x29, 0x06, 0x19, 0x29, 0x01,\n+\t0x82, 0x00, 0x10, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x29, 0x03,\n+\t0x00, 0x7D, 0x02, 0x00, 0x81, 0x2A, 0x02, 0x00, 0x51, 0x04, 0x64, 0x81,\n+\t0x13, 0x52, 0x04, 0x56, 0x81, 0x13, 0x81, 0x13, 0x53, 0x29, 0x06, 0x02,\n+\t0x36, 0x00, 0x28, 0x2C, 0x00, 0x02, 0x29, 0x01, 0x20, 0x13, 0x05, 0x02,\n+\t0x6C, 0x2A, 0x01, 0x0F, 0x13, 0x03, 0x00, 0x81, 0x24, 0x81, 0x0B, 0x2D,\n+\t0x01, 0x86, 0x03, 0x11, 0x06, 0x24, 0x81, 0x34, 0x29, 0x01, 0x81, 0x7F,\n+\t0x13, 0x5A, 0x01, 0x01, 0x12, 0x02, 0x00, 0x0F, 0x05, 0x02, 0x64, 0x2A,\n+\t0x01, 0x08, 0x12, 0x29, 0x01, 0x02, 0x0B, 0x39, 0x01, 0x06, 0x10, 0x38,\n+\t0x06, 0x02, 0x66, 0x2A, 0x04, 0x0D, 0x02, 0x00, 0x01, 0x01, 0x0F, 0x06,\n+\t0x04, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x20, 0x05, 0x02, 0x66, 0x2A,\n+\t0x81, 0x34, 0x29, 0x03, 0x01, 0x29, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02,\n+\t0x67, 0x2A, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x01, 0x4E, 0x29, 0x06, 0x01,\n+\t0x2A, 0x28, 0x81, 0x13, 0x00, 0x00, 0x1D, 0x81, 0x2E, 0x01, 0x0F, 0x0F,\n+\t0x05, 0x02, 0x6B, 0x2A, 0x00, 0x0A, 0x81, 0x2E, 0x01, 0x01, 0x0F, 0x05,\n+\t0x02, 0x6B, 0x2A, 0x81, 0x34, 0x29, 0x03, 0x00, 0x71, 0x3F, 0x72, 0x01,\n+\t0x20, 0x81, 0x2A, 0x81, 0x36, 0x29, 0x01, 0x20, 0x10, 0x06, 0x02, 0x6A,\n+\t0x2A, 0x29, 0x81, 0x06, 0x41, 0x81, 0x05, 0x46, 0x81, 0x2A, 0x1A, 0x03,\n+\t0x01, 0x81, 0x34, 0x81, 0x1C, 0x01, 0x00, 0x03, 0x02, 0x01, 0x00, 0x03,\n+\t0x03, 0x7B, 0x81, 0x18, 0x17, 0x39, 0x08, 0x03, 0x04, 0x03, 0x05, 0x29,\n+\t0x06, 0x80, 0x73, 0x81, 0x34, 0x29, 0x03, 0x06, 0x02, 0x01, 0x06, 0x0A,\n+\t0x29, 0x70, 0x2D, 0x0F, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x03, 0x29, 0x01,\n+\t0x81, 0x7F, 0x0F, 0x06, 0x0B, 0x81, 0x01, 0x2F, 0x06, 0x02, 0x63, 0x2A,\n+\t0x01, 0x7F, 0x03, 0x02, 0x29, 0x01, 0x81, 0xAC, 0x00, 0x0F, 0x06, 0x13,\n+\t0x02, 0x00, 0x81, 0x0E, 0x2D, 0x11, 0x02, 0x00, 0x81, 0x0D, 0x2D, 0x0B,\n+\t0x13, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x81, 0x38, 0x29, 0x56, 0x06,\n+\t0x03, 0x28, 0x04, 0x27, 0x01, 0x00, 0x81, 0x1A, 0x06, 0x0B, 0x01, 0x02,\n+\t0x0C, 0x73, 0x08, 0x02, 0x06, 0x46, 0x3F, 0x04, 0x16, 0x28, 0x02, 0x05,\n+\t0x02, 0x04, 0x11, 0x06, 0x02, 0x61, 0x2A, 0x02, 0x06, 0x02, 0x05, 0x3F,\n+\t0x02, 0x05, 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x09, 0x28, 0x01,\n+\t0x00, 0x03, 0x07, 0x81, 0x36, 0x81, 0x1C, 0x29, 0x06, 0x0A, 0x81, 0x36,\n+\t0x05, 0x04, 0x01, 0x7F, 0x03, 0x07, 0x04, 0x73, 0x81, 0x13, 0x01, 0x00,\n+\t0x81, 0x03, 0x41, 0x01, 0x88, 0x04, 0x7A, 0x3F, 0x01, 0x84, 0x80, 0x80,\n+\t0x00, 0x76, 0x40, 0x29, 0x06, 0x80, 0x4E, 0x81, 0x34, 0x81, 0x1C, 0x29,\n+\t0x06, 0x80, 0x44, 0x81, 0x34, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x05, 0x28,\n+\t0x81, 0x2D, 0x04, 0x34, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81,\n+\t0x2B, 0x04, 0x29, 0x01, 0x83, 0xFE, 0x01, 0x39, 0x0F, 0x06, 0x05, 0x28,\n+\t0x81, 0x2C, 0x04, 0x1C, 0x01, 0x0D, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81,\n+\t0x32, 0x04, 0x11, 0x01, 0x0A, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81, 0x33,\n+\t0x04, 0x06, 0x28, 0x81, 0x30, 0x01, 0x00, 0x28, 0x04, 0xFF, 0x38, 0x81,\n+\t0x13, 0x81, 0x13, 0x02, 0x01, 0x02, 0x03, 0x13, 0x03, 0x01, 0x02, 0x00,\n+\t0x56, 0x06, 0x0A, 0x71, 0x2D, 0x81, 0x0F, 0x3F, 0x01, 0x80, 0x56, 0x81,\n+\t0x19, 0x81, 0x0D, 0x2D, 0x29, 0x02, 0x00, 0x10, 0x06, 0x03, 0x28, 0x02,\n+\t0x00, 0x29, 0x01, 0x86, 0x00, 0x0B, 0x06, 0x02, 0x65, 0x2A, 0x02, 0x00,\n+\t0x81, 0x0E, 0x2D, 0x0B, 0x06, 0x05, 0x01, 0x80, 0x46, 0x81, 0x19, 0x02,\n+\t0x01, 0x06, 0x12, 0x81, 0x0B, 0x2D, 0x02, 0x00, 0x0D, 0x06, 0x06, 0x28,\n+\t0x81, 0x0B, 0x2D, 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x29, 0x81, 0x0B,\n+\t0x3F, 0x29, 0x81, 0x0C, 0x3F, 0x29, 0x81, 0x0F, 0x3F, 0x01, 0x86, 0x03,\n+\t0x11, 0x03, 0x08, 0x02, 0x02, 0x06, 0x05, 0x01, 0x02, 0x81, 0x01, 0x41,\n+\t0x02, 0x07, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19, 0x43, 0x28, 0x01, 0x82,\n+\t0x01, 0x07, 0x7A, 0x2D, 0x13, 0x29, 0x7A, 0x3F, 0x29, 0x01, 0x81, 0x7F,\n+\t0x13, 0x57, 0x36, 0x46, 0x01, 0x08, 0x12, 0x57, 0x01, 0x02, 0x13, 0x38,\n+\t0x03, 0x09, 0x76, 0x2E, 0x42, 0x13, 0x29, 0x76, 0x40, 0x05, 0x04, 0x01,\n+\t0x00, 0x03, 0x09, 0x02, 0x01, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x81, 0x05,\n+\t0x01, 0x20, 0x33, 0x01, 0x20, 0x81, 0x06, 0x41, 0x73, 0x29, 0x03, 0x05,\n+\t0x29, 0x02, 0x04, 0x0B, 0x06, 0x80, 0x4A, 0x29, 0x2D, 0x29, 0x81, 0x12,\n+\t0x29, 0x01, 0x0C, 0x12, 0x29, 0x01, 0x01, 0x0F, 0x46, 0x01, 0x02, 0x0F,\n+\t0x38, 0x06, 0x0A, 0x29, 0x02, 0x09, 0x13, 0x05, 0x04, 0x5D, 0x01, 0x00,\n+\t0x29, 0x02, 0x08, 0x05, 0x0E, 0x29, 0x01, 0x81, 0x70, 0x13, 0x01, 0x20,\n+\t0x0E, 0x06, 0x04, 0x5D, 0x01, 0x00, 0x29, 0x29, 0x06, 0x10, 0x02, 0x05,\n+\t0x5C, 0x3F, 0x02, 0x05, 0x3F, 0x02, 0x05, 0x01, 0x04, 0x08, 0x03, 0x05,\n+\t0x04, 0x01, 0x5D, 0x01, 0x04, 0x08, 0x04, 0xFF, 0x2F, 0x28, 0x02, 0x05,\n+\t0x73, 0x09, 0x01, 0x02, 0x12, 0x29, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19,\n+\t0x74, 0x41, 0x18, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19, 0x01, 0x00, 0x00,\n+\t0x00, 0x81, 0x28, 0x81, 0x27, 0x00, 0x04, 0x70, 0x2D, 0x81, 0x41, 0x06,\n+\t0x19, 0x81, 0x34, 0x29, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02, 0x67, 0x2A,\n+\t0x29, 0x03, 0x00, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x00, 0x70, 0x2D, 0x81,\n+\t0x1D, 0x26, 0x70, 0x2D, 0x29, 0x81, 0x3F, 0x46, 0x81, 0x3E, 0x03, 0x01,\n+\t0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x38, 0x06, 0x17, 0x81, 0x36, 0x29,\n+\t0x03, 0x03, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x03, 0x70, 0x2D, 0x81, 0x1D,\n+\t0x02, 0x02, 0x06, 0x03, 0x25, 0x04, 0x01, 0x23, 0x81, 0x13, 0x00, 0x00,\n+\t0x81, 0x2E, 0x01, 0x10, 0x0F, 0x05, 0x02, 0x6B, 0x2A, 0x00, 0x00, 0x81,\n+\t0x14, 0x81, 0x2E, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x6B, 0x2A, 0x7D, 0x01,\n+\t0x0C, 0x08, 0x01, 0x0C, 0x81, 0x2A, 0x81, 0x13, 0x7D, 0x29, 0x01, 0x0C,\n+\t0x08, 0x01, 0x0C, 0x31, 0x05, 0x02, 0x5F, 0x2A, 0x00, 0x02, 0x03, 0x00,\n+\t0x03, 0x01, 0x02, 0x00, 0x81, 0x10, 0x02, 0x01, 0x02, 0x00, 0x3B, 0x29,\n+\t0x01, 0x00, 0x0F, 0x06, 0x02, 0x5D, 0x00, 0x81, 0x44, 0x04, 0x73, 0x00,\n+\t0x81, 0x34, 0x01, 0x01, 0x0E, 0x06, 0x02, 0x60, 0x2A, 0x81, 0x36, 0x29,\n+\t0x29, 0x58, 0x46, 0x01, 0x05, 0x11, 0x38, 0x06, 0x02, 0x60, 0x2A, 0x01,\n+\t0x08, 0x08, 0x29, 0x7C, 0x2F, 0x0B, 0x06, 0x0D, 0x29, 0x01, 0x01, 0x46,\n+\t0x0C, 0x3E, 0x29, 0x7C, 0x41, 0x7E, 0x41, 0x04, 0x01, 0x28, 0x00, 0x00,\n+\t0x81, 0x34, 0x81, 0x01, 0x2F, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x15, 0x28,\n+\t0x01, 0x01, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x81, 0x36, 0x06, 0x02, 0x63,\n+\t0x2A, 0x01, 0x02, 0x81, 0x01, 0x41, 0x04, 0x2B, 0x01, 0x02, 0x39, 0x0F,\n+\t0x06, 0x22, 0x28, 0x01, 0x0D, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x81, 0x36,\n+\t0x01, 0x0C, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x7D, 0x01, 0x0C, 0x81, 0x2A,\n+\t0x81, 0x02, 0x7D, 0x01, 0x0C, 0x31, 0x05, 0x02, 0x63, 0x2A, 0x04, 0x03,\n+\t0x63, 0x2A, 0x28, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x34, 0x81,\n+\t0x1C, 0x29, 0x06, 0x24, 0x81, 0x36, 0x06, 0x04, 0x81, 0x30, 0x04, 0x1A,\n+\t0x81, 0x34, 0x29, 0x01, 0x81, 0x7F, 0x0D, 0x06, 0x0F, 0x29, 0x81, 0x03,\n+\t0x08, 0x01, 0x00, 0x46, 0x41, 0x81, 0x03, 0x46, 0x81, 0x2A, 0x04, 0x02,\n+\t0x81, 0x3C, 0x04, 0x59, 0x81, 0x13, 0x81, 0x13, 0x00, 0x00, 0x81, 0x2F,\n+\t0x29, 0x58, 0x06, 0x07, 0x28, 0x06, 0x02, 0x61, 0x2A, 0x04, 0x73, 0x00,\n+\t0x00, 0x81, 0x37, 0x01, 0x03, 0x81, 0x35, 0x46, 0x28, 0x46, 0x00, 0x00,\n+\t0x81, 0x34, 0x81, 0x3C, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x81, 0x34,\n+\t0x81, 0x1C, 0x29, 0x06, 0x34, 0x81, 0x36, 0x03, 0x01, 0x81, 0x36, 0x03,\n+\t0x02, 0x02, 0x01, 0x01, 0x02, 0x11, 0x02, 0x01, 0x01, 0x06, 0x0D, 0x13,\n+\t0x02, 0x02, 0x01, 0x01, 0x0F, 0x02, 0x02, 0x01, 0x03, 0x0F, 0x38, 0x13,\n+\t0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x5B, 0x01, 0x02, 0x0C,\n+\t0x02, 0x01, 0x08, 0x0C, 0x38, 0x03, 0x00, 0x04, 0x49, 0x81, 0x13, 0x02,\n+\t0x00, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x31, 0x7A, 0x3F, 0x81,\n+\t0x13, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x34, 0x81, 0x1C, 0x01,\n+\t0x00, 0x76, 0x40, 0x29, 0x06, 0x16, 0x81, 0x34, 0x29, 0x01, 0x20, 0x0B,\n+\t0x06, 0x0B, 0x01, 0x01, 0x46, 0x0C, 0x76, 0x2E, 0x38, 0x76, 0x40, 0x04,\n+\t0x01, 0x28, 0x04, 0x67, 0x81, 0x13, 0x81, 0x13, 0x00, 0x00, 0x01, 0x02,\n+\t0x81, 0x10, 0x81, 0x37, 0x01, 0x08, 0x0C, 0x81, 0x37, 0x08, 0x00, 0x00,\n+\t0x01, 0x03, 0x81, 0x10, 0x81, 0x37, 0x01, 0x08, 0x0C, 0x81, 0x37, 0x08,\n+\t0x01, 0x08, 0x0C, 0x81, 0x37, 0x08, 0x00, 0x00, 0x01, 0x01, 0x81, 0x10,\n+\t0x81, 0x37, 0x00, 0x00, 0x3C, 0x29, 0x56, 0x05, 0x01, 0x00, 0x28, 0x81,\n+\t0x44, 0x04, 0x75, 0x02, 0x03, 0x00, 0x81, 0x0A, 0x2F, 0x03, 0x01, 0x01,\n+\t0x00, 0x29, 0x02, 0x01, 0x0B, 0x06, 0x11, 0x29, 0x01, 0x01, 0x0C, 0x81,\n+\t0x09, 0x08, 0x2D, 0x02, 0x00, 0x0F, 0x06, 0x01, 0x00, 0x5A, 0x04, 0x69,\n+\t0x28, 0x01, 0x7F, 0x00, 0x00, 0x2B, 0x19, 0x37, 0x06, 0x05, 0x81, 0x42,\n+\t0x28, 0x04, 0x77, 0x01, 0x16, 0x81, 0x00, 0x41, 0x01, 0x00, 0x81, 0x55,\n+\t0x01, 0x00, 0x81, 0x54, 0x2B, 0x01, 0x17, 0x81, 0x00, 0x41, 0x00, 0x00,\n+\t0x01, 0x15, 0x81, 0x00, 0x41, 0x46, 0x50, 0x28, 0x50, 0x28, 0x2B, 0x00,\n+\t0x00, 0x01, 0x01, 0x46, 0x81, 0x3A, 0x00, 0x00, 0x46, 0x39, 0x81, 0x10,\n+\t0x46, 0x29, 0x06, 0x06, 0x81, 0x37, 0x28, 0x5B, 0x04, 0x77, 0x28, 0x00,\n+\t0x02, 0x03, 0x00, 0x70, 0x2D, 0x81, 0x12, 0x03, 0x01, 0x02, 0x01, 0x01,\n+\t0x0F, 0x13, 0x02, 0x01, 0x01, 0x04, 0x12, 0x01, 0x0F, 0x13, 0x02, 0x01,\n+\t0x01, 0x08, 0x12, 0x01, 0x0F, 0x13, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x10,\n+\t0x28, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01,\n+\t0x4A, 0x04, 0x80, 0x56, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x10, 0x28, 0x01,\n+\t0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04,\n+\t0x80, 0x40, 0x01, 0x02, 0x39, 0x0F, 0x06, 0x0F, 0x28, 0x01, 0x01, 0x01,\n+\t0x20, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x2B, 0x01,\n+\t0x03, 0x39, 0x0F, 0x06, 0x0E, 0x28, 0x28, 0x01, 0x10, 0x02, 0x00, 0x06,\n+\t0x03, 0x47, 0x04, 0x01, 0x48, 0x04, 0x17, 0x01, 0x04, 0x39, 0x0F, 0x06,\n+\t0x0E, 0x28, 0x28, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x47, 0x04, 0x01,\n+\t0x48, 0x04, 0x03, 0x62, 0x2A, 0x28, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C,\n+\t0x12, 0x01, 0x02, 0x10, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C, 0x12, 0x29,\n+\t0x59, 0x46, 0x01, 0x03, 0x0B, 0x13, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C,\n+\t0x12, 0x01, 0x01, 0x0F, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C, 0x12, 0x58,\n+\t0x00, 0x00, 0x1B, 0x01, 0x00, 0x6D, 0x2F, 0x29, 0x06, 0x20, 0x01, 0x01,\n+\t0x39, 0x0F, 0x06, 0x07, 0x28, 0x01, 0x00, 0x81, 0x16, 0x04, 0x11, 0x01,\n+\t0x02, 0x39, 0x0F, 0x06, 0x0A, 0x28, 0x6F, 0x2F, 0x06, 0x03, 0x01, 0x10,\n+\t0x38, 0x04, 0x01, 0x28, 0x04, 0x01, 0x28, 0x75, 0x2F, 0x05, 0x35, 0x30,\n+\t0x06, 0x32, 0x7F, 0x2F, 0x01, 0x14, 0x39, 0x0F, 0x06, 0x06, 0x28, 0x01,\n+\t0x02, 0x38, 0x04, 0x24, 0x01, 0x15, 0x39, 0x0F, 0x06, 0x0B, 0x28, 0x81,\n+\t0x1F, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x16, 0x04, 0x13, 0x01, 0x16, 0x39,\n+\t0x0F, 0x06, 0x06, 0x28, 0x01, 0x01, 0x38, 0x04, 0x07, 0x28, 0x01, 0x04,\n+\t0x38, 0x01, 0x00, 0x28, 0x19, 0x06, 0x03, 0x01, 0x08, 0x38, 0x00, 0x00,\n+\t0x1B, 0x29, 0x05, 0x10, 0x30, 0x06, 0x0D, 0x7F, 0x2F, 0x01, 0x15, 0x0F,\n+\t0x06, 0x05, 0x28, 0x81, 0x1F, 0x04, 0x01, 0x22, 0x00, 0x00, 0x81, 0x42,\n+\t0x01, 0x07, 0x13, 0x01, 0x01, 0x10, 0x06, 0x02, 0x6B, 0x2A, 0x00, 0x01,\n+\t0x03, 0x00, 0x2B, 0x19, 0x06, 0x06, 0x02, 0x00, 0x81, 0x00, 0x41, 0x00,\n+\t0x81, 0x42, 0x28, 0x04, 0x72, 0x00, 0x01, 0x14, 0x81, 0x45, 0x01, 0x01,\n+\t0x81, 0x55, 0x2B, 0x29, 0x01, 0x00, 0x81, 0x3D, 0x01, 0x16, 0x81, 0x45,\n+\t0x81, 0x49, 0x2B, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x55, 0x4C, 0x29, 0x29,\n+\t0x01, 0x03, 0x08, 0x81, 0x54, 0x81, 0x54, 0x14, 0x29, 0x56, 0x06, 0x02,\n+\t0x28, 0x00, 0x81, 0x54, 0x1E, 0x29, 0x06, 0x06, 0x7D, 0x46, 0x81, 0x4D,\n+\t0x04, 0x76, 0x28, 0x04, 0x6A, 0x00, 0x01, 0x00, 0x81, 0x4F, 0x81, 0x0B,\n+\t0x2D, 0x01, 0x86, 0x03, 0x11, 0x06, 0x06, 0x5C, 0x01, 0x00, 0x81, 0x50,\n+\t0x08, 0x4B, 0x08, 0x01, 0x03, 0x08, 0x01, 0x0D, 0x81, 0x55, 0x81, 0x54,\n+\t0x01, 0x00, 0x81, 0x4F, 0x81, 0x55, 0x01, 0x01, 0x81, 0x4F, 0x28, 0x81,\n+\t0x0B, 0x2D, 0x01, 0x86, 0x03, 0x11, 0x06, 0x0B, 0x01, 0x00, 0x81, 0x50,\n+\t0x81, 0x53, 0x01, 0x01, 0x81, 0x50, 0x28, 0x4B, 0x81, 0x53, 0x16, 0x15,\n+\t0x29, 0x56, 0x06, 0x02, 0x28, 0x00, 0x81, 0x53, 0x1F, 0x29, 0x06, 0x06,\n+\t0x7D, 0x46, 0x81, 0x4D, 0x04, 0x76, 0x28, 0x04, 0x6A, 0x00, 0x81, 0x14,\n+\t0x01, 0x14, 0x81, 0x55, 0x01, 0x0C, 0x81, 0x54, 0x7D, 0x01, 0x0C, 0x81,\n+\t0x4D, 0x00, 0x03, 0x03, 0x00, 0x01, 0x02, 0x81, 0x55, 0x01, 0x80, 0x46,\n+\t0x81, 0x01, 0x2F, 0x01, 0x02, 0x0F, 0x06, 0x0C, 0x02, 0x00, 0x06, 0x04,\n+\t0x01, 0x05, 0x04, 0x02, 0x01, 0x1D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x01,\n+\t0x7E, 0x2F, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02, 0x01, 0x00, 0x03, 0x02,\n+\t0x02, 0x01, 0x02, 0x02, 0x08, 0x29, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08,\n+\t0x81, 0x54, 0x81, 0x0B, 0x2D, 0x81, 0x53, 0x81, 0x04, 0x01, 0x04, 0x17,\n+\t0x81, 0x04, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x33, 0x81, 0x04, 0x01, 0x20,\n+\t0x81, 0x4D, 0x01, 0x20, 0x81, 0x55, 0x81, 0x05, 0x01, 0x20, 0x81, 0x4D,\n+\t0x70, 0x2D, 0x81, 0x53, 0x01, 0x00, 0x81, 0x55, 0x02, 0x01, 0x02, 0x02,\n+\t0x08, 0x29, 0x06, 0x31, 0x81, 0x53, 0x02, 0x01, 0x29, 0x06, 0x14, 0x01,\n+\t0x83, 0xFE, 0x01, 0x81, 0x53, 0x01, 0x04, 0x09, 0x29, 0x81, 0x53, 0x5B,\n+\t0x81, 0x02, 0x46, 0x81, 0x4E, 0x04, 0x01, 0x28, 0x02, 0x02, 0x06, 0x0F,\n+\t0x01, 0x01, 0x81, 0x53, 0x01, 0x01, 0x81, 0x53, 0x7E, 0x2F, 0x01, 0x08,\n+\t0x09, 0x81, 0x55, 0x04, 0x01, 0x28, 0x00, 0x00, 0x01, 0x0E, 0x81, 0x55,\n+\t0x01, 0x00, 0x81, 0x54, 0x00, 0x03, 0x70, 0x2D, 0x81, 0x3F, 0x05, 0x01,\n+\t0x00, 0x76, 0x2E, 0x01, 0x00, 0x81, 0x18, 0x12, 0x01, 0x01, 0x13, 0x58,\n+\t0x06, 0x03, 0x5A, 0x04, 0x74, 0x03, 0x00, 0x28, 0x02, 0x00, 0x24, 0x29,\n+\t0x56, 0x06, 0x02, 0x36, 0x2A, 0x03, 0x01, 0x81, 0x0B, 0x2D, 0x01, 0x86,\n+\t0x03, 0x11, 0x03, 0x02, 0x01, 0x0C, 0x81, 0x55, 0x02, 0x01, 0x78, 0x2F,\n+\t0x08, 0x02, 0x02, 0x01, 0x02, 0x13, 0x08, 0x01, 0x06, 0x08, 0x81, 0x54,\n+\t0x01, 0x03, 0x81, 0x55, 0x02, 0x00, 0x81, 0x53, 0x77, 0x78, 0x2F, 0x81,\n+\t0x4E, 0x02, 0x02, 0x06, 0x11, 0x81, 0x08, 0x2F, 0x81, 0x55, 0x70, 0x2D,\n+\t0x81, 0x40, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x08, 0x81, 0x55, 0x02, 0x01,\n+\t0x81, 0x53, 0x7D, 0x02, 0x01, 0x81, 0x4D, 0x00, 0x00, 0x4F, 0x29, 0x01,\n+\t0x00, 0x0F, 0x06, 0x02, 0x5D, 0x00, 0x81, 0x42, 0x28, 0x04, 0x72, 0x00,\n+\t0x29, 0x81, 0x55, 0x81, 0x4D, 0x00, 0x00, 0x01, 0x00, 0x70, 0x2D, 0x81,\n+\t0x3E, 0x06, 0x0E, 0x5C, 0x39, 0x06, 0x0A, 0x01, 0x80, 0x41, 0x81, 0x55,\n+\t0x01, 0x80, 0x42, 0x81, 0x55, 0x45, 0x06, 0x08, 0x5A, 0x39, 0x06, 0x04,\n+\t0x01, 0x01, 0x81, 0x55, 0x44, 0x06, 0x09, 0x5A, 0x39, 0x06, 0x05, 0x01,\n+\t0x80, 0x40, 0x81, 0x55, 0x46, 0x28, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00,\n+\t0x45, 0x44, 0x38, 0x05, 0x16, 0x01, 0x01, 0x01, 0x80, 0x7C, 0x81, 0x51,\n+\t0x03, 0x00, 0x01, 0x03, 0x01, 0x80, 0x7C, 0x81, 0x51, 0x02, 0x00, 0x08,\n+\t0x46, 0x28, 0x00, 0x45, 0x06, 0x08, 0x01, 0x01, 0x43, 0x28, 0x81, 0x51,\n+\t0x03, 0x00, 0x44, 0x06, 0x0B, 0x01, 0x03, 0x43, 0x28, 0x81, 0x51, 0x02,\n+\t0x00, 0x08, 0x03, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,\n+\t0x04, 0x81, 0x52, 0x01, 0x05, 0x81, 0x52, 0x01, 0x06, 0x81, 0x52, 0x01,\n+\t0x03, 0x81, 0x52, 0x01, 0x02, 0x81, 0x52, 0x0A, 0x5D, 0x00, 0x01, 0x03,\n+\t0x00, 0x39, 0x01, 0x01, 0x02, 0x00, 0x0C, 0x13, 0x05, 0x01, 0x00, 0x5C,\n+\t0x01, 0x03, 0x3A, 0x06, 0x09, 0x02, 0x00, 0x81, 0x55, 0x01, 0x02, 0x3A,\n+\t0x81, 0x55, 0x00, 0x00, 0x29, 0x01, 0x08, 0x4D, 0x81, 0x55, 0x81, 0x55,\n+\t0x00, 0x00, 0x29, 0x01, 0x10, 0x4D, 0x81, 0x55, 0x81, 0x53, 0x00, 0x00,\n+\t0x29, 0x50, 0x06, 0x02, 0x28, 0x00, 0x81, 0x42, 0x28, 0x04, 0x75\n };\n \n static const uint16_t t0_caddr[] \u003d {\n@@ -613,101 +788,117 @@ static const uint16_t t0_caddr[] \u003d {\n \t75,\n \t79,\n \t83,\n-\t88,\n-\t93,\n-\t98,\n-\t103,\n-\t108,\n-\t113,\n-\t118,\n-\t123,\n-\t128,\n-\t133,\n-\t138,\n-\t143,\n-\t148,\n-\t153,\n+\t87,\n+\t91,\n+\t95,\n+\t99,\n+\t104,\n+\t109,\n+\t114,\n+\t119,\n+\t124,\n+\t129,\n+\t134,\n+\t139,\n+\t144,\n+\t149,\n+\t154,\n \t159,\n \t164,\n \t169,\n-\t174,\n-\t179,\n-\t184,\n-\t189,\n-\t194,\n-\t199,\n-\t204,\n-\t209,\n-\t214,\n-\t219,\n-\t224,\n-\t229,\n-\t234,\n-\t239,\n-\t244,\n-\t249,\n-\t254,\n-\t259,\n-\t268,\n-\t272,\n-\t297,\n-\t303,\n-\t323,\n-\t334,\n-\t371,\n-\t431,\n-\t435,\n-\t471,\n-\t481,\n-\t557,\n-\t571,\n-\t577,\n-\t637,\n-\t657,\n-\t710,\n-\t1267,\n-\t1352,\n-\t1385,\n-\t1410,\n-\t1458,\n-\t1532,\n-\t1581,\n-\t1596,\n-\t1607,\n-\t1613,\n-\t1684,\n-\t1725,\n-\t1738,\n-\t1757,\n-\t1764,\n-\t1776,\n-\t1811,\n-\t1840,\n-\t1852,\n-\t1859,\n-\t1875,\n-\t2013,\n-\t2022,\n-\t2035,\n-\t2044,\n-\t2051,\n-\t2157,\n-\t2179,\n-\t2193,\n+\t175,\n+\t180,\n+\t185,\n+\t190,\n+\t195,\n+\t200,\n+\t205,\n+\t210,\n+\t215,\n+\t220,\n+\t225,\n+\t230,\n+\t235,\n+\t240,\n+\t245,\n+\t250,\n+\t255,\n+\t260,\n+\t265,\n+\t270,\n+\t275,\n+\t284,\n+\t288,\n+\t316,\n+\t322,\n+\t343,\n+\t354,\n+\t391,\n+\t523,\n+\t527,\n+\t563,\n+\t573,\n+\t650,\n+\t664,\n+\t671,\n+\t731,\n+\t752,\n+\t776,\n+\t829,\n+\t915,\n+\t1023,\n+\t1035,\n+\t1630,\n+\t1636,\n+\t1713,\n+\t1724,\n+\t1759,\n+\t1785,\n+\t1833,\n+\t1910,\n+\t1963,\n+\t1978,\n+\t1989,\n+\t1995,\n+\t2064,\n+\t2076,\n+\t2119,\n+\t2133,\n+\t2153,\n+\t2161,\n+\t2173,\n \t2210,\n-\t2233,\n-\t2269,\n-\t2285,\n-\t2439,\n-\t2449,\n-\t2558,\n-\t2573,\n-\t2580,\n-\t2590,\n-\t2600\n+\t2241,\n+\t2254,\n+\t2261,\n+\t2278,\n+\t2417,\n+\t2427,\n+\t2441,\n+\t2451,\n+\t2459,\n+\t2565,\n+\t2587,\n+\t2601,\n+\t2619,\n+\t2642,\n+\t2679,\n+\t2767,\n+\t2784,\n+\t2945,\n+\t2955,\n+\t3066,\n+\t3081,\n+\t3088,\n+\t3137,\n+\t3198,\n+\t3224,\n+\t3253,\n+\t3263,\n+\t3273\n };\n \n-#define T0_INTERPRETED 68\n+#define T0_INTERPRETED 86\n \n #define T0_ENTER(ip, rp, slot) do { \u005c\n \t\tconst unsigned char *t0_newip; \u005c\n@@ -728,7 +919,7 @@ name(void *ctx) \u005c\n \tT0_ENTER(t0ctx-\u003eip, t0ctx-\u003erp, slot); \u005c\n }\n \n-T0_DEFENTRY(br_ssl_hs_server_init_main, 133)\n+T0_DEFENTRY(br_ssl_hs_server_init_main, 155)\n \n void\n br_ssl_hs_server_run(void *t0ctx)\n@@ -853,6 +1044,11 @@ br_ssl_hs_server_run(void *t0ctx)\n \t\t\t\t}\n \t\t\t\tbreak;\n \t\t\tcase 10: {\n+\t\t\t\t/* -rot */\n+ T0_NROT(); \n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 11: {\n \t\t\t\t/* \u003c */\n \n \tint32_t b \u003d T0_POPi();\n@@ -861,7 +1057,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 11: {\n+\t\t\tcase 12: {\n \t\t\t\t/* \u003c\u003c */\n \n \tint c \u003d (int)T0_POPi();\n@@ -870,7 +1066,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 12: {\n+\t\t\tcase 13: {\n \t\t\t\t/* \u003c\u003d */\n \n \tint32_t b \u003d T0_POPi();\n@@ -879,7 +1075,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 13: {\n+\t\t\tcase 14: {\n \t\t\t\t/* \u003c\u003e */\n \n \tuint32_t b \u003d T0_POP();\n@@ -888,7 +1084,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 14: {\n+\t\t\tcase 15: {\n \t\t\t\t/* \u003d */\n \n \tuint32_t b \u003d T0_POP();\n@@ -897,7 +1093,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 15: {\n+\t\t\tcase 16: {\n \t\t\t\t/* \u003e */\n \n \tint32_t b \u003d T0_POPi();\n@@ -906,7 +1102,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 16: {\n+\t\t\tcase 17: {\n \t\t\t\t/* \u003e\u003d */\n \n \tint32_t b \u003d T0_POPi();\n@@ -915,7 +1111,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 17: {\n+\t\t\tcase 18: {\n \t\t\t\t/* \u003e\u003e */\n \n \tint c \u003d (int)T0_POPi();\n@@ -924,7 +1120,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 18: {\n+\t\t\tcase 19: {\n \t\t\t\t/* and */\n \n \tuint32_t b \u003d T0_POP();\n@@ -933,22 +1129,49 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 19: {\n+\t\t\tcase 20: {\n \t\t\t\t/* begin-cert */\n \n-\tif (CTX-\u003echain_len \u003d\u003d 0) {\n+\tif (ENG-\u003echain_len \u003d\u003d 0) {\n \t\tT0_PUSHi(-1);\n \t} else {\n-\t\tCTX-\u003ecert_cur \u003d CTX-\u003echain-\u003edata;\n-\t\tCTX-\u003ecert_len \u003d CTX-\u003echain-\u003edata_len;\n-\t\tCTX-\u003echain ++;\n-\t\tCTX-\u003echain_len --;\n-\t\tT0_PUSH(CTX-\u003ecert_len);\n+\t\tENG-\u003ecert_cur \u003d ENG-\u003echain-\u003edata;\n+\t\tENG-\u003ecert_len \u003d ENG-\u003echain-\u003edata_len;\n+\t\tENG-\u003echain ++;\n+\t\tENG-\u003echain_len --;\n+\t\tT0_PUSH(ENG-\u003ecert_len);\n \t}\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 20: {\n+\t\t\tcase 21: {\n+\t\t\t\t/* begin-ta-name */\n+\n+\tconst br_x500_name *dn;\n+\tif (CTX-\u003ecur_dn_index \u003e\u003d CTX-\u003enum_tas) {\n+\t\tT0_PUSHi(-1);\n+\t} else {\n+\t\tif (CTX-\u003eta_names \u003d\u003d NULL) {\n+\t\t\tdn \u003d \u0026CTX-\u003etas[CTX-\u003ecur_dn_index].dn;\n+\t\t} else {\n+\t\t\tdn \u003d \u0026CTX-\u003eta_names[CTX-\u003ecur_dn_index];\n+\t\t}\n+\t\tCTX-\u003ecur_dn_index ++;\n+\t\tCTX-\u003ecur_dn \u003d dn-\u003edata;\n+\t\tCTX-\u003ecur_dn_len \u003d dn-\u003elen;\n+\t\tT0_PUSH(CTX-\u003ecur_dn_len);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 22: {\n+\t\t\t\t/* begin-ta-name-list */\n+\n+\tCTX-\u003ecur_dn_index \u003d 0;\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 23: {\n \t\t\t\t/* bzero */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -957,7 +1180,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 21: {\n+\t\t\tcase 24: {\n \t\t\t\t/* call-policy-handler */\n \n \tint x;\n@@ -967,20 +1190,20 @@ br_ssl_hs_server_run(void *t0ctx)\n \t\tCTX-\u003epolicy_vtable, CTX, \u0026choices);\n \tENG-\u003esession.cipher_suite \u003d choices.cipher_suite;\n \tCTX-\u003esign_hash_id \u003d choices.hash_id;\n-\tCTX-\u003echain \u003d choices.chain;\n-\tCTX-\u003echain_len \u003d choices.chain_len;\n+\tENG-\u003echain \u003d choices.chain;\n+\tENG-\u003echain_len \u003d choices.chain_len;\n \tT0_PUSHi(-(x !\u003d 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 22: {\n+\t\t\tcase 25: {\n \t\t\t\t/* can-output? */\n \n \tT0_PUSHi(-(ENG-\u003ehlen_out \u003e 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 23: {\n+\t\t\tcase 26: {\n \t\t\t\t/* check-resume */\n \n \tif (ENG-\u003esession.session_id_len \u003d\u003d 32\n@@ -994,12 +1217,12 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 24: {\n+\t\t\tcase 27: {\n \t\t\t\t/* co */\n T0_CO(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 25: {\n+\t\t\tcase 28: {\n \t\t\t\t/* compute-Finished-inner */\n \n \tint prf_id \u003d T0_POP();\n@@ -1022,23 +1245,75 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 26: {\n+\t\t\tcase 29: {\n+\t\t\t\t/* compute-hash-CV */\n+\n+\tint i;\n+\n+\tfor (i \u003d 1; i \u003c\u003d 6; i ++) {\n+\t\tbr_multihash_out(\u0026ENG-\u003emhash, i,\n+\t\t\tENG-\u003epad + HASH_PAD_OFF[i - 1]);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 30: {\n \t\t\t\t/* copy-cert-chunk */\n \n \tsize_t clen;\n \n-\tclen \u003d CTX-\u003ecert_len;\n+\tclen \u003d ENG-\u003ecert_len;\n \tif (clen \u003e sizeof ENG-\u003epad) {\n \t\tclen \u003d sizeof ENG-\u003epad;\n \t}\n-\tmemcpy(ENG-\u003epad, CTX-\u003ecert_cur, clen);\n-\tCTX-\u003ecert_cur +\u003d clen;\n-\tCTX-\u003ecert_len -\u003d clen;\n+\tmemcpy(ENG-\u003epad, ENG-\u003ecert_cur, clen);\n+\tENG-\u003ecert_cur +\u003d clen;\n+\tENG-\u003ecert_len -\u003d clen;\n \tT0_PUSH(clen);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 27: {\n+\t\t\tcase 31: {\n+\t\t\t\t/* copy-dn-chunk */\n+\n+\tsize_t clen;\n+\n+\tclen \u003d CTX-\u003ecur_dn_len;\n+\tif (clen \u003e sizeof ENG-\u003epad) {\n+\t\tclen \u003d sizeof ENG-\u003epad;\n+\t}\n+\tmemcpy(ENG-\u003epad, CTX-\u003ecur_dn, clen);\n+\tCTX-\u003ecur_dn +\u003d clen;\n+\tCTX-\u003ecur_dn_len -\u003d clen;\n+\tT0_PUSH(clen);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 32: {\n+\t\t\t\t/* copy-hash-CV */\n+\n+\tint id \u003d T0_POP();\n+\tsize_t off, len;\n+\n+\tif (id \u003d\u003d 0) {\n+\t\toff \u003d 0;\n+\t\tlen \u003d 36;\n+\t} else {\n+\t\tif (br_multihash_getimpl(\u0026ENG-\u003emhash, id) \u003d\u003d 0) {\n+\t\t\tT0_PUSH(0);\n+\t\t\tT0_RET();\n+\t\t}\n+\t\toff \u003d HASH_PAD_OFF[id - 1];\n+\t\tlen \u003d HASH_PAD_OFF[id] - off;\n+\t}\n+\tmemcpy(CTX-\u003ehash_CV, ENG-\u003epad + off, len);\n+\tCTX-\u003ehash_CV_len \u003d len;\n+\tCTX-\u003ehash_CV_id \u003d id;\n+\tT0_PUSHi(-1);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 33: {\n \t\t\t\t/* data-get8 */\n \n \tsize_t addr \u003d T0_POP();\n@@ -1046,14 +1321,14 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 28: {\n+\t\t\tcase 34: {\n \t\t\t\t/* discard-input */\n \n \tENG-\u003ehlen_in \u003d 0;\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 29: {\n+\t\t\tcase 35: {\n \t\t\t\t/* do-ecdh */\n \n \tint prf_id \u003d T0_POPi();\n@@ -1062,7 +1337,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 30: {\n+\t\t\tcase 36: {\n \t\t\t\t/* do-ecdhe-part1 */\n \n \tint curve \u003d T0_POPi();\n@@ -1070,7 +1345,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 31: {\n+\t\t\tcase 37: {\n \t\t\t\t/* do-ecdhe-part2 */\n \n \tint prf_id \u003d T0_POPi();\n@@ -1079,7 +1354,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 32: {\n+\t\t\tcase 38: {\n \t\t\t\t/* do-rsa-decrypt */\n \n \tint prf_id \u003d T0_POPi();\n@@ -1088,17 +1363,24 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 33: {\n+\t\t\tcase 39: {\n+\t\t\t\t/* do-static-ecdh */\n+\n+\tdo_static_ecdh(CTX, T0_POP());\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 40: {\n \t\t\t\t/* drop */\n (void)T0_POP(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 34: {\n+\t\t\tcase 41: {\n \t\t\t\t/* dup */\n T0_PUSH(T0_PEEK(0)); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 35: {\n+\t\t\tcase 42: {\n \t\t\t\t/* fail */\n \n \tbr_ssl_engine_fail(ENG, (int)T0_POPi());\n@@ -1106,14 +1388,31 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 36: {\n+\t\t\tcase 43: {\n \t\t\t\t/* flush-record */\n \n \tbr_ssl_engine_flush_record(ENG);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 37: {\n+\t\t\tcase 44: {\n+\t\t\t\t/* get-key-type-usages */\n+\n+\tconst br_x509_class *xc;\n+\tconst br_x509_pkey *pk;\n+\tunsigned usages;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tpk \u003d xc-\u003eget_pkey(ENG-\u003ex509ctx, \u0026usages);\n+\tif (pk \u003d\u003d NULL) {\n+\t\tT0_PUSH(0);\n+\t} else {\n+\t\tT0_PUSH(pk-\u003ekey_type | usages);\n+\t}\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 45: {\n \t\t\t\t/* get16 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1121,7 +1420,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 38: {\n+\t\t\tcase 46: {\n \t\t\t\t/* get32 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1129,7 +1428,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 39: {\n+\t\t\tcase 47: {\n \t\t\t\t/* get8 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1137,14 +1436,14 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 40: {\n+\t\t\tcase 48: {\n \t\t\t\t/* has-input? */\n \n \tT0_PUSHi(-(ENG-\u003ehlen_in !\u003d 0));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 41: {\n+\t\t\tcase 49: {\n \t\t\t\t/* memcmp */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1155,7 +1454,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 42: {\n+\t\t\tcase 50: {\n \t\t\t\t/* memcpy */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1165,7 +1464,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 43: {\n+\t\t\tcase 51: {\n \t\t\t\t/* mkrand */\n \n \tsize_t len \u003d (size_t)T0_POP();\n@@ -1174,21 +1473,21 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 44: {\n+\t\t\tcase 52: {\n \t\t\t\t/* more-incoming-bytes? */\n \n \tT0_PUSHi(ENG-\u003ehlen_in !\u003d 0 || !br_ssl_engine_recvrec_finished(ENG));\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 45: {\n+\t\t\tcase 53: {\n \t\t\t\t/* multihash-init */\n \n \tbr_multihash_init(\u0026ENG-\u003emhash);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 46: {\n+\t\t\tcase 54: {\n \t\t\t\t/* neg */\n \n \tuint32_t a \u003d T0_POP();\n@@ -1196,7 +1495,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 47: {\n+\t\t\tcase 55: {\n \t\t\t\t/* not */\n \n \tuint32_t a \u003d T0_POP();\n@@ -1204,7 +1503,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 48: {\n+\t\t\tcase 56: {\n \t\t\t\t/* or */\n \n \tuint32_t b \u003d T0_POP();\n@@ -1213,12 +1512,17 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 49: {\n+\t\t\tcase 57: {\n \t\t\t\t/* over */\n T0_PUSH(T0_PEEK(1)); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 50: {\n+\t\t\tcase 58: {\n+\t\t\t\t/* pick */\n+ T0_PICK(T0_POP()); \n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 59: {\n \t\t\t\t/* read-chunk-native */\n \n \tsize_t clen \u003d ENG-\u003ehlen_in;\n@@ -1242,7 +1546,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 51: {\n+\t\t\tcase 60: {\n \t\t\t\t/* read8-native */\n \n \tif (ENG-\u003ehlen_in \u003e 0) {\n@@ -1260,7 +1564,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 52: {\n+\t\t\tcase 61: {\n \t\t\t\t/* save-session */\n \n \tif (CTX-\u003ecache_vtable !\u003d NULL) {\n@@ -1270,7 +1574,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 53: {\n+\t\t\tcase 62: {\n \t\t\t\t/* set-max-frag-len */\n \n \tsize_t max_frag_len \u003d T0_POP();\n@@ -1289,7 +1593,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 54: {\n+\t\t\tcase 63: {\n \t\t\t\t/* set16 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1297,7 +1601,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 55: {\n+\t\t\tcase 64: {\n \t\t\t\t/* set32 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1305,7 +1609,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 56: {\n+\t\t\tcase 65: {\n \t\t\t\t/* set8 */\n \n \tsize_t addr \u003d (size_t)T0_POP();\n@@ -1313,7 +1617,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 57: {\n+\t\t\tcase 66: {\n \t\t\t\t/* supported-curves */\n \n \tuint32_t x \u003d ENG-\u003eiec \u003d\u003d NULL ? 0 : ENG-\u003eiec-\u003esupported_curves;\n@@ -1321,7 +1625,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 58: {\n+\t\t\tcase 67: {\n \t\t\t\t/* supported-hash-functions */\n \n \tint i;\n@@ -1340,12 +1644,26 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 59: {\n+\t\t\tcase 68: {\n+\t\t\t\t/* supports-ecdsa? */\n+\n+\tT0_PUSHi(-(ENG-\u003eiecdsa !\u003d 0));\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 69: {\n+\t\t\t\t/* supports-rsa-sign? */\n+\n+\tT0_PUSHi(-(ENG-\u003eirsavrfy !\u003d 0));\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 70: {\n \t\t\t\t/* swap */\n T0_SWAP(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 60: {\n+\t\t\tcase 71: {\n \t\t\t\t/* switch-aesgcm-in */\n \n \tint is_client, prf_id;\n@@ -1359,7 +1677,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 61: {\n+\t\t\tcase 72: {\n \t\t\t\t/* switch-aesgcm-out */\n \n \tint is_client, prf_id;\n@@ -1373,7 +1691,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 62: {\n+\t\t\tcase 73: {\n \t\t\t\t/* switch-cbc-in */\n \n \tint is_client, prf_id, mac_id, aes;\n@@ -1389,7 +1707,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 63: {\n+\t\t\tcase 74: {\n \t\t\t\t/* switch-cbc-out */\n \n \tint is_client, prf_id, mac_id, aes;\n@@ -1405,21 +1723,40 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 64: {\n+\t\t\tcase 75: {\n+\t\t\t\t/* ta-names-total-length */\n+\n+\tsize_t u, len;\n+\n+\tlen \u003d 0;\n+\tif (CTX-\u003eta_names !\u003d NULL) {\n+\t\tfor (u \u003d 0; u \u003c CTX-\u003enum_tas; u ++) {\n+\t\t\tlen +\u003d CTX-\u003eta_names[u].len + 2;\n+\t\t}\n+\t} else if (CTX-\u003etas !\u003d NULL) {\n+\t\tfor (u \u003d 0; u \u003c CTX-\u003enum_tas; u ++) {\n+\t\t\tlen +\u003d CTX-\u003etas[u].dn.len + 2;\n+\t\t}\n+\t}\n+\tT0_PUSH(len);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 76: {\n \t\t\t\t/* total-chain-length */\n \n \tsize_t u;\n \tuint32_t total;\n \n \ttotal \u003d 0;\n-\tfor (u \u003d 0; u \u003c CTX-\u003echain_len; u ++) {\n-\t\ttotal +\u003d 3 + (uint32_t)CTX-\u003echain[u].data_len;\n+\tfor (u \u003d 0; u \u003c ENG-\u003echain_len; u ++) {\n+\t\ttotal +\u003d 3 + (uint32_t)ENG-\u003echain[u].data_len;\n \t}\n \tT0_PUSH(total);\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 65: {\n+\t\t\tcase 77: {\n \t\t\t\t/* u\u003e\u003e */\n \n \tint c \u003d (int)T0_POPi();\n@@ -1428,7 +1765,17 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 66: {\n+\t\t\tcase 78: {\n+\t\t\t\t/* verify-CV-sig */\n+\n+\tint err;\n+\n+\terr \u003d verify_CV_sig(CTX, T0_POP());\n+\tT0_PUSHi(err);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 79: {\n \t\t\t\t/* write-blob-chunk */\n \n \tsize_t clen \u003d ENG-\u003ehlen_out;\n@@ -1452,7 +1799,7 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 67: {\n+\t\t\tcase 80: {\n \t\t\t\t/* write8-native */\n \n \tunsigned char x;\n@@ -1471,6 +1818,60 @@ br_ssl_hs_server_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n+\t\t\tcase 81: {\n+\t\t\t\t/* x509-append */\n+\n+\tconst br_x509_class *xc;\n+\tsize_t len;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tlen \u003d T0_POP();\n+\txc-\u003eappend(ENG-\u003ex509ctx, ENG-\u003epad, len);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 82: {\n+\t\t\t\t/* x509-end-cert */\n+\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003eend_cert(ENG-\u003ex509ctx);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 83: {\n+\t\t\t\t/* x509-end-chain */\n+\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\tT0_PUSH(xc-\u003eend_chain(ENG-\u003ex509ctx));\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 84: {\n+\t\t\t\t/* x509-start-cert */\n+\n+\tconst br_x509_class *xc;\n+\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003estart_cert(ENG-\u003ex509ctx, T0_POP());\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase 85: {\n+\t\t\t\t/* x509-start-chain */\n+\n+\tconst br_x509_class *xc;\n+\tuint32_t bc;\n+\n+\tbc \u003d T0_POP();\n+\txc \u003d *(ENG-\u003ex509ctx);\n+\txc-\u003estart_chain(ENG-\u003ex509ctx, bc ? ENG-\u003eserver_name : NULL);\n+\n+\t\t\t\t}\n+\t\t\t\tbreak;\n \t\t\t}\n \n \t\t} else {\ndiff --git a/src/ssl/ssl_hs_server.t0 b/src/ssl/ssl_hs_server.t0\nindex 8176429..862e0fb 100644\n--- a/src/ssl/ssl_hs_server.t0\n+++ b/src/ssl/ssl_hs_server.t0\n@@ -141,6 +141,35 @@ do_ecdh(br_ssl_server_context *ctx, int prf_id,\n }\n \n /*\n+ * Do the full static ECDH key exchange. When this function is called,\n+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),\n+ * and the client's public key (from its certificate) has type EC and is\n+ * apt for key exchange.\n+ */\n+static void\n+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)\n+{\n+\tunsigned char cpoint[133];\n+\tsize_t cpoint_len;\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tcpoint_len \u003d pk-\u003ekey.ec.qlen;\n+\tif (cpoint_len \u003e sizeof cpoint) {\n+\t\t/*\n+\t\t * If the point is larger than our buffer then we need to\n+\t\t * restrict it. Length 2 is not a valid point length, so\n+\t\t * the ECDH will fail.\n+\t\t */\n+\t\tcpoint_len \u003d 2;\n+\t}\n+\tmemcpy(cpoint, pk-\u003ekey.ec.q, cpoint_len);\n+\tdo_ecdh(ctx, prf_id, cpoint, cpoint_len);\n+}\n+\n+/*\n * Do the ECDHE key exchange (part 1: generation of transient key, and\n * computing of the point to send to the client). Returned value is the\n * signature length (in bytes), or -x on error (with x being an error\n@@ -258,6 +287,94 @@ do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,\n \tmemset(ctx-\u003eecdhe_key, 0, ctx-\u003eecdhe_key_len);\n }\n \n+/*\n+ * Offset for hash value within the pad (when obtaining all hash values,\n+ * in preparation for verification of the CertificateVerify message).\n+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value\n+ * is used to get the total length.\n+ */\n+static const unsigned char HASH_PAD_OFF[] \u003d { 0, 16, 36, 64, 96, 144, 208 };\n+\n+/*\n+ * OID for hash functions in RSA signatures.\n+ */\n+static const unsigned char HASH_OID_SHA1[] \u003d {\n+\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n+};\n+\n+static const unsigned char HASH_OID_SHA224[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n+};\n+\n+static const unsigned char HASH_OID_SHA256[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n+};\n+\n+static const unsigned char HASH_OID_SHA384[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n+};\n+\n+static const unsigned char HASH_OID_SHA512[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n+};\n+\n+static const unsigned char *HASH_OID[] \u003d {\n+\tHASH_OID_SHA1,\n+\tHASH_OID_SHA224,\n+\tHASH_OID_SHA256,\n+\tHASH_OID_SHA384,\n+\tHASH_OID_SHA512\n+};\n+\n+/*\n+ * Verify the signature in CertificateVerify. Returned value is 0 on\n+ * success, or a non-zero error code. Lack of implementation of the\n+ * designated signature algorithm is reported as a \u0022bad signature\u0022\n+ * error (because it means that the peer did not honour our advertised\n+ * set of supported signature algorithms).\n+ */\n+static int\n+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)\n+{\n+\tconst br_x509_class **xc;\n+\tconst br_x509_pkey *pk;\n+\tint id;\n+\n+\tid \u003d ctx-\u003ehash_CV_id;\n+\txc \u003d ctx-\u003eeng.x509ctx;\n+\tpk \u003d (*xc)-\u003eget_pkey(xc, NULL);\n+\tif (pk-\u003ekey_type \u003d\u003d BR_KEYTYPE_RSA) {\n+\t\tunsigned char tmp[64];\n+\t\tconst unsigned char *hash_oid;\n+\n+\t\tif (id \u003d\u003d 0) {\n+\t\t\thash_oid \u003d NULL;\n+\t\t} else {\n+\t\t\thash_oid \u003d HASH_OID[id - 2];\n+\t\t}\n+\t\tif (ctx-\u003eeng.irsavrfy \u003d\u003d 0) {\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t\tif (!ctx-\u003eeng.irsavrfy(ctx-\u003eeng.pad, sig_len,\n+\t\t\thash_oid, ctx-\u003ehash_CV_len, \u0026pk-\u003ekey.rsa, tmp)\n+\t\t\t|| memcmp(tmp, ctx-\u003ehash_CV, ctx-\u003ehash_CV_len) !\u003d 0)\n+\t\t{\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t} else {\n+\t\tif (ctx-\u003eeng.iecdsa \u003d\u003d 0) {\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t\tif (!ctx-\u003eeng.iecdsa(ctx-\u003eeng.iec,\n+\t\t\tctx-\u003ehash_CV, ctx-\u003ehash_CV_len,\n+\t\t\t\u0026pk-\u003ekey.ec, ctx-\u003eeng.pad, sig_len))\n+\t\t{\n+\t\t\treturn BR_ERR_BAD_SIGNATURE;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n }\n \n \u005c \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n@@ -386,26 +503,7 @@ cc: set-max-frag-len ( len -- ) {\n \t\u005c Open extension value.\n \tread16 open-elt\n \n-\t\u005c Clear list of supported signature algorithms.\n-\t0 addr-hashes set16\n-\n-\t\u005c Get list of algorithms length.\n-\tread16 open-elt\n-\tbegin dup while\n-\t\tread8 { hash } read8 { sign }\n-\t\t\u005c We keep the value if the signature is either 1 (RSA) or\n-\t\t\u005c 3 (ECDSA), and the hash is one of the SHA-* functions\n-\t\t\u005c (2 to 6, from SHA-1 to SHA-512). Note that we reject\n-\t\t\u005c any use of MD5. Also, we do not keep track of the client\n-\t\t\u005c preferences.\n-\t\thash 2 \u003e\u003d hash 6 \u003c\u003d and\n-\t\tsign 1 \u003d sign 3 \u003d or\n-\t\tand if\n-\t\t\taddr-hashes get16\n-\t\t\t1 sign 1- 2 \u003c\u003c hash + \u003c\u003c or addr-hashes set16\n-\t\tthen\n-\trepeat\n-\tclose-elt\n+\tread-list-sign-algos addr-hashes set16\n \n \t\u005c Close extension value.\n \tclose-elt ;\n@@ -440,8 +538,8 @@ cc: call-policy-handler ( -- bool ) {\n \t\tCTX-\u003epolicy_vtable, CTX, \u0026choices);\n \tENG-\u003esession.cipher_suite \u003d choices.cipher_suite;\n \tCTX-\u003esign_hash_id \u003d choices.hash_id;\n-\tCTX-\u003echain \u003d choices.chain;\n-\tCTX-\u003echain_len \u003d choices.chain_len;\n+\tENG-\u003echain \u003d choices.chain;\n+\tENG-\u003echain_len \u003d choices.chain_len;\n \tT0_PUSHi(-(x !\u003d 0));\n }\n \n@@ -667,11 +765,14 @@ cc: save-session ( -- ) {\n \tok-compression ifnot 40 fail-alert then\n \n \t\u005c Filter hash function support by what the server also supports.\n-\t\u005c If no common hash function remains, then ECDHE suites are not\n-\t\u005c possible.\n+\t\u005c If no common hash function remains with RSA and/or ECDSA, then\n+\t\u005c the corresponding ECDHE suites are not possible.\n \tsupported-hash-functions drop 257 *\n \taddr-hashes get16 and dup addr-hashes set16\n-\t0\u003c\u003e { can-ecdhe }\n+\t\u005c In 'can-ecdhe', bit 12 is set if ECDHE_RSA is possible, bit 13 is\n+\t\u005c set if ECDHE_ECDSA is possible.\n+\tdup 0xFF and 0\u003c\u003e neg\n+\tswap 8 \u003e\u003e 0\u003c\u003e 2 and or { can-ecdhe }\n \n \t\u005c Filter supported curves. If there is no common curve between\n \t\u005c client and us, then ECDHE suites cannot be used. Note that we\n@@ -684,6 +785,11 @@ cc: save-session ( -- ) {\n \tresume if -1 ret then\n \n \t\u005c We are not resuming, so a new session ID should be generated.\n+\t\u005c We don't check that the new ID is distinct from the one sent\n+\t\u005c by the client because probability of such an event is 2^(-256),\n+\t\u005c i.e. much (much) lower than that of an undetected transmission\n+\t\u005c error or hardware miscomputation, and with similar consequences\n+\t\u005c (handshake simply fails).\n \taddr-session_id 32 mkrand\n \t32 addr-session_id_len set8\n \n@@ -692,14 +798,14 @@ cc: save-session ( -- ) {\n \t\u005c server preference order is enforced, and also in case some\n \t\u005c suites are filtered out. In particular:\n \t\u005c -- ECDHE suites are removed if there is no common hash function\n-\t\u005c (for signatures) or no common curve.\n+\t\u005c (for the relevant signature algorithm) or no common curve.\n \t\u005c -- TLS-1.2-only suites are removed if the negociated version is\n \t\u005c TLS-1.1 or lower.\n \taddr-client_suites dup \u003ecss-off\n \tbegin dup css-max \u003c while\n \t\tdup get16 dup cipher-suite-to-elements\n-\t\tcan-ecdhe ifnot\n-\t\t\tdup 12 \u003e\u003e dup 1 \u003d swap 2 \u003d or if\n+\t\tdup 12 \u003e\u003e dup 1 \u003d swap 2 \u003d or if\n+\t\t\tdup can-ecdhe and ifnot\n \t\t\t\t2drop 0 dup\n \t\t\tthen\n \t\tthen\n@@ -791,63 +897,6 @@ cc: save-session ( -- ) {\n \t\tdrop\n \tthen ;\n \n-\u005c Compute total chain length. This includes the individual certificate\n-\u005c headers, but not the total chain header. This also sets the cert_cur,\n-\u005c cert_len and chain_len context fields.\n-cc: total-chain-length ( -- len ) {\n-\tsize_t u;\n-\tuint32_t total;\n-\n-\ttotal \u003d 0;\n-\tfor (u \u003d 0; u \u003c CTX-\u003echain_len; u ++) {\n-\t\ttotal +\u003d 3 + (uint32_t)CTX-\u003echain[u].data_len;\n-\t}\n-\tT0_PUSH(total);\n-}\n-\n-\u005c Get length for current certificate in the chain; if the chain end was\n-\u005c reached, then this returns -1.\n-cc: begin-cert ( -- len ) {\n-\tif (CTX-\u003echain_len \u003d\u003d 0) {\n-\t\tT0_PUSHi(-1);\n-\t} else {\n-\t\tCTX-\u003ecert_cur \u003d CTX-\u003echain-\u003edata;\n-\t\tCTX-\u003ecert_len \u003d CTX-\u003echain-\u003edata_len;\n-\t\tCTX-\u003echain ++;\n-\t\tCTX-\u003echain_len --;\n-\t\tT0_PUSH(CTX-\u003ecert_len);\n-\t}\n-}\n-\n-\u005c Copy a chunk of certificate data into the pad. Returned value is the\n-\u005c chunk length, or 0 if the certificate end is reached.\n-cc: copy-cert-chunk ( -- len ) {\n-\tsize_t clen;\n-\n-\tclen \u003d CTX-\u003ecert_len;\n-\tif (clen \u003e sizeof ENG-\u003epad) {\n-\t\tclen \u003d sizeof ENG-\u003epad;\n-\t}\n-\tmemcpy(ENG-\u003epad, CTX-\u003ecert_cur, clen);\n-\tCTX-\u003ecert_cur +\u003d clen;\n-\tCTX-\u003ecert_len -\u003d clen;\n-\tT0_PUSH(clen);\n-}\n-\n-\u005c Write the server Certificate.\n-: write-Certificate ( -- )\n-\t11 write8\n-\ttotal-chain-length\n-\tdup 3 + write24 write24\n-\tbegin\n-\t\tbegin-cert\n-\t\tdup 0\u003c if drop ret then write24\n-\t\tbegin copy-cert-chunk dup while\n-\t\t\taddr-pad swap write-blob\n-\t\trepeat\n-\t\tdrop\n-\tagain ;\n-\n \u005c Do the first part of ECDHE. Returned value is the computed signature\n \u005c length, or a negative error code on error.\n cc: do-ecdhe-part1 ( curve -- len ) {\n@@ -900,6 +949,166 @@ cc: do-ecdhe-part1 ( curve -- len ) {\n \tsig-len write16\n \taddr-pad sig-len write-blob ;\n \n+\u005c Get length of the list of anchor names to send to the client. The length\n+\u005c includes the per-name 2-byte header, but _not_ the 2-byte header for\n+\u005c the list itself. If no client certificate is requested, then this\n+\u005c returns 0.\n+cc: ta-names-total-length ( -- len ) {\n+\tsize_t u, len;\n+\n+\tlen \u003d 0;\n+\tif (CTX-\u003eta_names !\u003d NULL) {\n+\t\tfor (u \u003d 0; u \u003c CTX-\u003enum_tas; u ++) {\n+\t\t\tlen +\u003d CTX-\u003eta_names[u].len + 2;\n+\t\t}\n+\t} else if (CTX-\u003etas !\u003d NULL) {\n+\t\tfor (u \u003d 0; u \u003c CTX-\u003enum_tas; u ++) {\n+\t\t\tlen +\u003d CTX-\u003etas[u].dn.len + 2;\n+\t\t}\n+\t}\n+\tT0_PUSH(len);\n+}\n+\n+\u005c Compute length and optionally write the contents of the list of\n+\u005c supported client authentication methods.\n+: write-list-auth ( do_write -- len )\n+\t0\n+\taddr-cipher_suite get16 use-ecdh? if\n+\t\t2+ over if 65 write8 66 write8 then\n+\tthen\n+\tsupports-rsa-sign? if 1+ over if 1 write8 then then\n+\tsupports-ecdsa? if 1+ over if 64 write8 then then\n+\tswap drop ;\n+\n+: write-signhash-inner2 ( dow algo hashes len id -- dow algo hashes len )\n+\t{ id }\n+\tover 1 id \u003c\u003c and ifnot ret then\n+\t2+\n+\t3 pick if id write8 2 pick write8 then ;\n+\n+: write-signhash-inner1 ( dow algo hashes -- dow len )\n+\t0\n+\t4 write-signhash-inner2\n+\t5 write-signhash-inner2\n+\t6 write-signhash-inner2\n+\t3 write-signhash-inner2\n+\t2 write-signhash-inner2\n+\t-rot 2drop ;\n+\n+\u005c Compute length and optionally write the contents of the list of\n+\u005c supported sign+hash algorithms.\n+: write-list-signhash ( do_write -- len )\n+\t0 { len }\n+\t\u005c If supporting neither RSA nor ECDSA in the engine, then we\n+\t\u005c will do only static ECDH, and thus we claim support for\n+\t\u005c everything (for the X.509 validator).\n+\tsupports-rsa-sign? supports-ecdsa? or ifnot\n+\t\t1 0x7C write-signhash-inner1 \u003elen\n+\t\t3 0x7C write-signhash-inner1 len +\n+\t\tswap drop ret\n+\tthen\n+\tsupports-rsa-sign? if\n+\t\t1 supported-hash-functions drop\n+\t\twrite-signhash-inner1 \u003elen\n+\tthen\n+\tsupports-ecdsa? if\n+\t\t3 supported-hash-functions drop\n+\t\twrite-signhash-inner1 len + \u003elen\n+\tthen\n+\tdrop len ;\n+\n+\u005c Initialise index for sending the list of anchor DN.\n+cc: begin-ta-name-list ( -- ) {\n+\tCTX-\u003ecur_dn_index \u003d 0;\n+}\n+\n+\u005c Switch to next DN in the list. Returned value is the DN length, or -1\n+\u005c if the end of the list was reached.\n+cc: begin-ta-name ( -- len ) {\n+\tconst br_x500_name *dn;\n+\tif (CTX-\u003ecur_dn_index \u003e\u003d CTX-\u003enum_tas) {\n+\t\tT0_PUSHi(-1);\n+\t} else {\n+\t\tif (CTX-\u003eta_names \u003d\u003d NULL) {\n+\t\t\tdn \u003d \u0026CTX-\u003etas[CTX-\u003ecur_dn_index].dn;\n+\t\t} else {\n+\t\t\tdn \u003d \u0026CTX-\u003eta_names[CTX-\u003ecur_dn_index];\n+\t\t}\n+\t\tCTX-\u003ecur_dn_index ++;\n+\t\tCTX-\u003ecur_dn \u003d dn-\u003edata;\n+\t\tCTX-\u003ecur_dn_len \u003d dn-\u003elen;\n+\t\tT0_PUSH(CTX-\u003ecur_dn_len);\n+\t}\n+}\n+\n+\u005c Copy a chunk of the current DN into the pad. Returned value is the\n+\u005c chunk length; this is 0 when the end of the current DN is reached.\n+cc: copy-dn-chunk ( -- len ) {\n+\tsize_t clen;\n+\n+\tclen \u003d CTX-\u003ecur_dn_len;\n+\tif (clen \u003e sizeof ENG-\u003epad) {\n+\t\tclen \u003d sizeof ENG-\u003epad;\n+\t}\n+\tmemcpy(ENG-\u003epad, CTX-\u003ecur_dn, clen);\n+\tCTX-\u003ecur_dn +\u003d clen;\n+\tCTX-\u003ecur_dn_len -\u003d clen;\n+\tT0_PUSH(clen);\n+}\n+\n+\u005c Write a CertificateRequest message.\n+: write-CertificateRequest ( -- )\n+\t\u005c The list of client authentication types includes:\n+\t\u005c rsa_sign (1)\n+\t\u005c ecdsa_sign (64)\n+\t\u005c rsa_fixed_ecdh (65)\n+\t\u005c ecdsa_fixed_ecdh (66)\n+\t\u005c rsa_sign and ecdsa_sign require, respectively, RSA and ECDSA\n+\t\u005c support. Static ECDH requires that the cipher suite is ECDH.\n+\t\u005c When we ask for static ECDH, we always send both rsa_fixed_ecdh\n+\t\u005c and ecdsa_fixed_ecdh because what matters there is what the\n+\t\u005c X.509 engine may support, and we do not control that.\n+\t\u005c\n+\t\u005c With TLS 1.2, we must also send a list of supported signature\n+\t\u005c and hash algorithms. That list is supposed to qualify both\n+\t\u005c the engine itself, and the X.509 validator, which are separate\n+\t\u005c in BearSSL. There again, we use the engine capabilities in that\n+\t\u005c list, and resort to a generic all-support list if only\n+\t\u005c static ECDH is accepted.\n+\t\u005c\n+\t\u005c (In practice, client implementations tend to have at most one\n+\t\u005c or two certificates, and send the chain regardless of what\n+\t\u005c algorithms are used in it.)\n+\n+\t0 write-list-auth\n+\taddr-version get16 0x0303 \u003e\u003d if\n+\t\t2+ 0 write-list-signhash +\n+\tthen\n+\tta-names-total-length + 3 +\n+\n+\t\u005c Message header\n+\t13 write8 write24\n+\n+\t\u005c List of authentication methods\n+\t0 write-list-auth write8 1 write-list-auth drop\n+\n+\t\u005c For TLS 1.2+, list of sign+hash\n+\taddr-version get16 0x0303 \u003e\u003d if\n+\t\t0 write-list-signhash write16 1 write-list-signhash drop\n+\tthen\n+\n+\t\u005c Trust anchor names\n+\tta-names-total-length write16\n+\tbegin-ta-name-list\n+\tbegin\n+\t\tbegin-ta-name\n+\t\tdup 0\u003c if drop ret then write16\n+\t\tbegin copy-dn-chunk dup while\n+\t\t\taddr-pad swap write-blob\n+\t\trepeat\n+\t\tdrop\n+\tagain ;\n+\n \u005c Write the Server Hello Done message.\n : write-ServerHelloDone ( -- )\n \t14 write8 0 write24 ;\n@@ -927,11 +1136,18 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {\n \tdo_ecdhe_part2(CTX, prf_id, ENG-\u003epad, len);\n }\n \n-\u005c Read the Client Key Exchange.\n-: read-ClientKeyExchange ( -- )\n-\t\u005c Get header, and check message type.\n-\tread-handshake-header 16 \u003d ifnot ERR_UNEXPECTED fail then\n+\u005c Perform static ECDH. The point from the client is the public key\n+\u005c extracted from its certificate.\n+cc: do-static-ecdh ( prf_id -- ) {\n+\tdo_static_ecdh(CTX, T0_POP());\n+}\n \n+\u005c Read a ClientKeyExchange header.\n+: read-ClientKeyExchange-header ( -- len )\n+\tread-handshake-header 16 \u003d ifnot ERR_UNEXPECTED fail then ;\n+\n+\u005c Read the Client Key Exchange contents (non-empty case).\n+: read-ClientKeyExchange-contents ( lim -- )\n \t\u005c What we should get depends on the cipher suite.\n \taddr-cipher_suite get16 use-rsa-keyx? if\n \t\t\u005c RSA key exchange: we expect a RSA-encrypted value.\n@@ -951,6 +1167,116 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {\n \tthen\n \tclose-elt ;\n \n+\u005c Read the Client Key Exchange (normal case).\n+: read-ClientKeyExchange ( -- )\n+\tread-ClientKeyExchange-header\n+\tread-ClientKeyExchange-contents ;\n+\n+\u005c Obtain all possible hash values for handshake messages so far. This\n+\u005c is done because we need the hash value for the CertificateVerify\n+\u005c _before_ knowing which hash function will actually be used, as this\n+\u005c information is obtained from decoding the message header itself.\n+\u005c All hash values are stored in the pad (208 bytes in total).\n+cc: compute-hash-CV ( -- ) {\n+\tint i;\n+\n+\tfor (i \u003d 1; i \u003c\u003d 6; i ++) {\n+\t\tbr_multihash_out(\u0026ENG-\u003emhash, i,\n+\t\t\tENG-\u003epad + HASH_PAD_OFF[i - 1]);\n+\t}\n+}\n+\n+\u005c Copy the proper hash value from the pad into the dedicated buffer.\n+\u005c Returned value is true (-1) on success, false (0) on error (error\n+\u005c being an unimplemented hash function). The id has already been verified\n+\u005c to be either 0 (for MD5+SHA-1) or one of the SHA-* functions.\n+cc: copy-hash-CV ( hash_id -- bool ) {\n+\tint id \u003d T0_POP();\n+\tsize_t off, len;\n+\n+\tif (id \u003d\u003d 0) {\n+\t\toff \u003d 0;\n+\t\tlen \u003d 36;\n+\t} else {\n+\t\tif (br_multihash_getimpl(\u0026ENG-\u003emhash, id) \u003d\u003d 0) {\n+\t\t\tT0_PUSH(0);\n+\t\t\tT0_RET();\n+\t\t}\n+\t\toff \u003d HASH_PAD_OFF[id - 1];\n+\t\tlen \u003d HASH_PAD_OFF[id] - off;\n+\t}\n+\tmemcpy(CTX-\u003ehash_CV, ENG-\u003epad + off, len);\n+\tCTX-\u003ehash_CV_len \u003d len;\n+\tCTX-\u003ehash_CV_id \u003d id;\n+\tT0_PUSHi(-1);\n+}\n+\n+\u005c Verify signature in CertificateVerify. Output is 0 on success, or a\n+\u005c non-zero error code.\n+cc: verify-CV-sig ( sig-len -- err ) {\n+\tint err;\n+\n+\terr \u003d verify_CV_sig(CTX, T0_POP());\n+\tT0_PUSHi(err);\n+}\n+\n+\u005c Process static ECDH.\n+: process-static-ECDH ( ktu -- )\n+\t\u005c Static ECDH is allowed only if the cipher suite uses ECDH, and\n+\t\u005c the client's public key has type EC and allows key exchange.\n+\t\u005c BR_KEYTYPE_KEYX is 0x10, and BR_KEYTYPE_EC is 2.\n+\t0x1F and 0x12 \u003d ifnot ERR_WRONG_KEY_USAGE fail then\n+\taddr-cipher_suite get16\n+\tdup use-ecdh? ifnot ERR_UNEXPECTED fail then\n+\tprf-id\n+\tdo-static-ecdh ;\n+\n+\u005c Read CertificateVerify header.\n+: read-CertificateVerify-header ( -- lim )\n+\tcompute-hash-CV\n+\tread-handshake-header 15 \u003d ifnot ERR_UNEXPECTED fail then ;\n+\n+\u005c Read CertificateVerify. The client key type + usage is expected on the\n+\u005c stack.\n+: read-CertificateVerify ( ktu -- )\n+\t\u005c Check that the key allows for signatures.\n+\tdup 0x20 and ifnot ERR_WRONG_KEY_USAGE fail then\n+\t0x0F and { key-type }\n+\n+\t\u005c Get header.\n+\tread-CertificateVerify-header\n+\n+\t\u005c With TLS 1.2+, there is an explicit hash + signature indication,\n+\t\u005c which must be compatible with the key type.\n+\taddr-version get16 0x0303 \u003e\u003d if\n+\t\t\u005c Get hash function, then signature algorithm. The\n+\t\t\u005c signature algorithm is 1 (RSA) or 3 (ECDSA) while our\n+\t\t\u005c symbolic constants for key types are 1 (RSA) or 2 (EC).\n+\t\tread16\n+\t\tdup 0xFF and 1+ 1 \u003e\u003e key-type \u003d ifnot\n+\t\t\tERR_BAD_SIGNATURE fail\n+\t\tthen\n+\t\t8 \u003e\u003e\n+\n+\t\t\u005c We support only SHA-1, SHA-224, SHA-256, SHA-384\n+\t\t\u005c and SHA-512. We explicitly reject MD5.\n+\t\tdup 2 \u003c over 6 \u003e or if ERR_INVALID_ALGORITHM fail then\n+\telse\n+\t\t\u005c With TLS 1.0 and 1.1, hash is MD5+SHA-1 (0) for RSA,\n+\t\t\u005c SHA-1 (2) for ECDSA.\n+\t\tkey-type 0x01 \u003d if 0 else 2 then\n+\tthen\n+\tcopy-hash-CV ifnot ERR_INVALID_ALGORITHM fail then\n+\n+\t\u005c Read signature.\n+\tread16 dup { sig-len }\n+\tdup 512 \u003e if ERR_LIMIT_EXCEEDED fail then\n+\taddr-pad swap read-blob\n+\tsig-len verify-CV-sig\n+\tdup if fail then drop\n+\n+\tclose-elt ;\n+\n \u005c Send a HelloRequest.\n : send-HelloRequest ( -- )\n \tflush-record\n@@ -974,11 +1300,54 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {\n \telse\n \t\t\u005c Not a session resumption\n \t\twrite-ServerHello\n-\t\twrite-Certificate\n+\t\twrite-Certificate drop\n \t\twrite-ServerKeyExchange\n+\t\tta-names-total-length if\n+\t\t\twrite-CertificateRequest\n+\t\tthen\n \t\twrite-ServerHelloDone\n \t\tflush-record\n-\t\tread-ClientKeyExchange\n+\n+\t\t\u005c If we sent a CertificateRequest then we expect a\n+\t\t\u005c Certificate message.\n+\t\tta-names-total-length if\n+\t\t\t\u005c Read client certificate.\n+\t\t\t0 read-Certificate\n+\n+\t\t\tchoice\n+\t\t\t\tdup 0\u003c uf\n+\t\t\t\t\t\u005c Client certificate validation failed.\n+\t\t\t\t\t2 flag? ifnot neg fail then\n+\t\t\t\t\tdrop\n+\t\t\t\t\tread-ClientKeyExchange\n+\t\t\t\t\tread-CertificateVerify-header\n+\t\t\t\t\tdup skip-blob drop\n+\t\t\t\tenduf\n+\t\t\t\tdup 0\u003d uf\n+\t\t\t\t\t\u005c Client sent no certificate at all.\n+\t\t\t\t\tdrop\n+\t\t\t\t\t2 flag? ifnot\n+\t\t\t\t\t\tERR_NO_CLIENT_AUTH fail\n+\t\t\t\t\tthen\n+\t\t\t\t\tread-ClientKeyExchange\n+\t\t\t\tenduf\n+\n+\t\t\t\t\u005c Client certificate was validated.\n+\t\t\t\tread-ClientKeyExchange-header\n+\t\t\t\tdup ifnot\n+\t\t\t\t\t\u005c Empty ClientKeyExchange.\n+\t\t\t\t\tdrop\n+\t\t\t\t\tprocess-static-ECDH\n+\t\t\t\telse\n+\t\t\t\t\tread-ClientKeyExchange-contents\n+\t\t\t\t\tread-CertificateVerify\n+\t\t\t\tthen\n+\t\t\tendchoice\n+\t\telse\n+\t\t\t\u005c No client certificate request, we just expect\n+\t\t\t\u005c a non-empty ClientKeyExchange.\n+\t\t\tread-ClientKeyExchange\n+\t\tthen\n \t\t0 read-CCS-Finished\n \t\t0 write-CCS-Finished\n \t\tsave-session\ndiff --git a/src/ssl/ssl_scert_single_ec.c b/src/ssl/ssl_scert_single_ec.c\nnew file mode 100644\nindex 0000000..2648670\n--- /dev/null\n+++ b/src/ssl/ssl_scert_single_ec.c\n@@ -0,0 +1,135 @@\n+/*\n+ * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining \n+ * a copy of this software and associated documentation files (the\n+ * \u0022Software\u0022), to deal in the Software without restriction, including\n+ * without limitation the rights to use, copy, modify, merge, publish,\n+ * distribute, sublicense, and/or sell copies of the Software, and to\n+ * permit persons to whom the Software is furnished to do so, subject to\n+ * the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be \n+ * included in all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+ * SOFTWARE.\n+ */\n+\n+#include \u0022inner.h\u0022\n+\n+static int\n+se_choose(const br_ssl_server_policy_class **pctx,\n+\tconst br_ssl_server_context *cc,\n+\tbr_ssl_server_choices *choices)\n+{\n+\tbr_ssl_server_policy_ec_context *pc;\n+\tconst br_suite_translated *st;\n+\tsize_t u, st_num;\n+\tint hash_id;\n+\n+\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n+\tst \u003d br_ssl_server_get_client_suites(cc, \u0026st_num);\n+\thash_id \u003d br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc) \u003e\u003e 8);\n+\tif (cc-\u003eeng.session.version \u003c BR_TLS12) {\n+\t\thash_id \u003d br_sha1_ID;\n+\t}\n+\tchoices-\u003echain \u003d pc-\u003echain;\n+\tchoices-\u003echain_len \u003d pc-\u003echain_len;\n+\tfor (u \u003d 0; u \u003c st_num; u ++) {\n+\t\tunsigned tt;\n+\n+\t\ttt \u003d st[u][1];\n+\t\tswitch (tt \u003e\u003e 12) {\n+\t\tcase BR_SSLKEYX_ECDH_RSA:\n+\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0\n+\t\t\t\t\u0026\u0026 pc-\u003ecert_issuer_key_type \u003d\u003d BR_KEYTYPE_RSA)\n+\t\t\t{\n+\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase BR_SSLKEYX_ECDH_ECDSA:\n+\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0\n+\t\t\t\t\u0026\u0026 pc-\u003ecert_issuer_key_type \u003d\u003d BR_KEYTYPE_EC)\n+\t\t\t{\n+\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase BR_SSLKEYX_ECDHE_ECDSA:\n+\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_SIGN) !\u003d 0\n+\t\t\t\t\u0026\u0026 hash_id !\u003d 0)\n+\t\t\t{\n+\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n+\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static uint32_t\n+se_do_keyx(const br_ssl_server_policy_class **pctx,\n+\tunsigned char *data, size_t len)\n+{\n+\tbr_ssl_server_policy_ec_context *pc;\n+\n+\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n+\treturn pc-\u003eiec-\u003emul(data, len, pc-\u003esk-\u003ex, pc-\u003esk-\u003exlen, pc-\u003esk-\u003ecurve);\n+}\n+\n+static size_t\n+se_do_sign(const br_ssl_server_policy_class **pctx,\n+\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n+{\n+\tbr_ssl_server_policy_ec_context *pc;\n+\tunsigned char hv[64];\n+\tconst br_hash_class *hc;\n+\n+\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n+\thc \u003d br_multihash_getimpl(pc-\u003emhash, hash_id);\n+\tif (hc \u003d\u003d NULL) {\n+\t\treturn 0;\n+\t}\n+\tmemcpy(hv, data, hv_len);\n+\tif (len \u003c 139) {\n+\t\treturn 0;\n+\t}\n+\treturn pc-\u003eiecdsa(pc-\u003eiec, hc, hv, pc-\u003esk, data);\n+}\n+\n+static const br_ssl_server_policy_class se_policy_vtable \u003d {\n+\tsizeof(br_ssl_server_policy_ec_context),\n+\tse_choose,\n+\tse_do_keyx,\n+\tse_do_sign\n+};\n+\n+/* see bearssl_ssl.h */\n+void\n+br_ssl_server_set_single_ec(br_ssl_server_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_ec_private_key *sk, unsigned allowed_usages,\n+\tunsigned cert_issuer_key_type,\n+\tconst br_ec_impl *iec, br_ecdsa_sign iecdsa)\n+{\n+\tcc-\u003echain_handler.single_ec.vtable \u003d \u0026se_policy_vtable;\n+\tcc-\u003echain_handler.single_ec.chain \u003d chain;\n+\tcc-\u003echain_handler.single_ec.chain_len \u003d chain_len;\n+\tcc-\u003echain_handler.single_ec.sk \u003d sk;\n+\tcc-\u003echain_handler.single_ec.allowed_usages \u003d allowed_usages;\n+\tcc-\u003echain_handler.single_ec.cert_issuer_key_type \u003d cert_issuer_key_type;\n+\tcc-\u003echain_handler.single_ec.mhash \u003d \u0026cc-\u003eeng.mhash;\n+\tcc-\u003echain_handler.single_ec.iec \u003d iec;\n+\tcc-\u003echain_handler.single_ec.iecdsa \u003d iecdsa;\n+\tcc-\u003epolicy_vtable \u003d \u0026cc-\u003echain_handler.single_ec.vtable;\n+}\ndiff --git a/src/ssl/ssl_scert_single_rsa.c b/src/ssl/ssl_scert_single_rsa.c\nnew file mode 100644\nindex 0000000..2ddbff9\n--- /dev/null\n+++ b/src/ssl/ssl_scert_single_rsa.c\n@@ -0,0 +1,158 @@\n+/*\n+ * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining \n+ * a copy of this software and associated documentation files (the\n+ * \u0022Software\u0022), to deal in the Software without restriction, including\n+ * without limitation the rights to use, copy, modify, merge, publish,\n+ * distribute, sublicense, and/or sell copies of the Software, and to\n+ * permit persons to whom the Software is furnished to do so, subject to\n+ * the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be \n+ * included in all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+ * SOFTWARE.\n+ */\n+\n+#include \u0022inner.h\u0022\n+\n+static int\n+sr_choose(const br_ssl_server_policy_class **pctx,\n+\tconst br_ssl_server_context *cc,\n+\tbr_ssl_server_choices *choices)\n+{\n+\tbr_ssl_server_policy_rsa_context *pc;\n+\tconst br_suite_translated *st;\n+\tsize_t u, st_num;\n+\tint hash_id;\n+\n+\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n+\tst \u003d br_ssl_server_get_client_suites(cc, \u0026st_num);\n+\thash_id \u003d br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc));\n+\tif (cc-\u003eeng.session.version \u003c BR_TLS12) {\n+\t\thash_id \u003d 0;\n+\t}\n+\tchoices-\u003echain \u003d pc-\u003echain;\n+\tchoices-\u003echain_len \u003d pc-\u003echain_len;\n+\tfor (u \u003d 0; u \u003c st_num; u ++) {\n+\t\tunsigned tt;\n+\n+\t\ttt \u003d st[u][1];\n+\t\tswitch (tt \u003e\u003e 12) {\n+\t\tcase BR_SSLKEYX_RSA:\n+\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0) {\n+\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase BR_SSLKEYX_ECDHE_RSA:\n+\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_SIGN) !\u003d 0\n+\t\t\t\t\u0026\u0026 hash_id !\u003d 0)\n+\t\t\t{\n+\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n+\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static uint32_t\n+sr_do_keyx(const br_ssl_server_policy_class **pctx,\n+\tunsigned char *data, size_t len)\n+{\n+\tbr_ssl_server_policy_rsa_context *pc;\n+\n+\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n+\treturn br_rsa_ssl_decrypt(pc-\u003eirsacore, pc-\u003esk, data, len);\n+}\n+\n+/*\n+ * OID for hash functions in RSA signatures.\n+ */\n+static const unsigned char HASH_OID_SHA1[] \u003d {\n+\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n+};\n+\n+static const unsigned char HASH_OID_SHA224[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n+};\n+\n+static const unsigned char HASH_OID_SHA256[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n+};\n+\n+static const unsigned char HASH_OID_SHA384[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n+};\n+\n+static const unsigned char HASH_OID_SHA512[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n+};\n+\n+static const unsigned char *HASH_OID[] \u003d {\n+\tHASH_OID_SHA1,\n+\tHASH_OID_SHA224,\n+\tHASH_OID_SHA256,\n+\tHASH_OID_SHA384,\n+\tHASH_OID_SHA512\n+};\n+\n+static size_t\n+sr_do_sign(const br_ssl_server_policy_class **pctx,\n+\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n+{\n+\tbr_ssl_server_policy_rsa_context *pc;\n+\tunsigned char hv[64];\n+\tsize_t sig_len;\n+\tconst unsigned char *hash_oid;\n+\n+\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n+\tmemcpy(hv, data, hv_len);\n+\tif (hash_id \u003d\u003d 0) {\n+\t\thash_oid \u003d NULL;\n+\t} else if (hash_id \u003e\u003d 2 \u0026\u0026 hash_id \u003c\u003d 6) {\n+\t\thash_oid \u003d HASH_OID[hash_id - 2];\n+\t} else {\n+\t\treturn 0;\n+\t}\n+\tsig_len \u003d (pc-\u003esk-\u003en_bitlen + 7) \u003e\u003e 3;\n+\tif (len \u003c sig_len) {\n+\t\treturn 0;\n+\t}\n+\treturn pc-\u003eirsasign(hash_oid, hv, hv_len, pc-\u003esk, data) ? sig_len : 0;\n+}\n+\n+static const br_ssl_server_policy_class sr_policy_vtable \u003d {\n+\tsizeof(br_ssl_server_policy_rsa_context),\n+\tsr_choose,\n+\tsr_do_keyx,\n+\tsr_do_sign\n+};\n+\n+/* see bearssl_ssl.h */\n+void\n+br_ssl_server_set_single_rsa(br_ssl_server_context *cc,\n+\tconst br_x509_certificate *chain, size_t chain_len,\n+\tconst br_rsa_private_key *sk, unsigned allowed_usages,\n+\tbr_rsa_private irsacore, br_rsa_pkcs1_sign irsasign)\n+{\n+\tcc-\u003echain_handler.single_rsa.vtable \u003d \u0026sr_policy_vtable;\n+\tcc-\u003echain_handler.single_rsa.chain \u003d chain;\n+\tcc-\u003echain_handler.single_rsa.chain_len \u003d chain_len;\n+\tcc-\u003echain_handler.single_rsa.sk \u003d sk;\n+\tcc-\u003echain_handler.single_rsa.allowed_usages \u003d allowed_usages;\n+\tcc-\u003echain_handler.single_rsa.irsacore \u003d irsacore;\n+\tcc-\u003echain_handler.single_rsa.irsasign \u003d irsasign;\n+\tcc-\u003epolicy_vtable \u003d \u0026cc-\u003echain_handler.single_rsa.vtable;\n+}\ndiff --git a/src/ssl/ssl_single_ec.c b/src/ssl/ssl_single_ec.c\ndeleted file mode 100644\nindex 4edaca3..0000000\n--- a/src/ssl/ssl_single_ec.c\n+++ /dev/null\n@@ -1,135 +0,0 @@\n-/*\n- * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n- *\n- * Permission is hereby granted, free of charge, to any person obtaining \n- * a copy of this software and associated documentation files (the\n- * \u0022Software\u0022), to deal in the Software without restriction, including\n- * without limitation the rights to use, copy, modify, merge, publish,\n- * distribute, sublicense, and/or sell copies of the Software, and to\n- * permit persons to whom the Software is furnished to do so, subject to\n- * the following conditions:\n- *\n- * The above copyright notice and this permission notice shall be \n- * included in all copies or substantial portions of the Software.\n- *\n- * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n- * SOFTWARE.\n- */\n-\n-#include \u0022inner.h\u0022\n-\n-static int\n-se_choose(const br_ssl_server_policy_class **pctx,\n-\tconst br_ssl_server_context *cc,\n-\tbr_ssl_server_choices *choices)\n-{\n-\tbr_ssl_server_policy_ec_context *pc;\n-\tconst br_suite_translated *st;\n-\tsize_t u, st_num;\n-\tint hash_id;\n-\n-\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n-\tst \u003d br_ssl_server_get_client_suites(cc, \u0026st_num);\n-\thash_id \u003d br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc));\n-\tif (cc-\u003eeng.session.version \u003c BR_TLS12) {\n-\t\thash_id \u003d br_sha1_ID;\n-\t}\n-\tchoices-\u003echain \u003d pc-\u003echain;\n-\tchoices-\u003echain_len \u003d pc-\u003echain_len;\n-\tfor (u \u003d 0; u \u003c st_num; u ++) {\n-\t\tunsigned tt;\n-\n-\t\ttt \u003d st[u][1];\n-\t\tswitch (tt \u003e\u003e 12) {\n-\t\tcase BR_SSLKEYX_ECDH_RSA:\n-\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0\n-\t\t\t\t\u0026\u0026 pc-\u003ecert_issuer_key_type \u003d\u003d BR_KEYTYPE_RSA)\n-\t\t\t{\n-\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase BR_SSLKEYX_ECDH_ECDSA:\n-\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0\n-\t\t\t\t\u0026\u0026 pc-\u003ecert_issuer_key_type \u003d\u003d BR_KEYTYPE_EC)\n-\t\t\t{\n-\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase BR_SSLKEYX_ECDHE_ECDSA:\n-\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_SIGN) !\u003d 0\n-\t\t\t\t\u0026\u0026 hash_id !\u003d 0)\n-\t\t\t{\n-\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n-\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-static uint32_t\n-se_do_keyx(const br_ssl_server_policy_class **pctx,\n-\tunsigned char *data, size_t len)\n-{\n-\tbr_ssl_server_policy_ec_context *pc;\n-\n-\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n-\treturn pc-\u003eiec-\u003emul(data, len, pc-\u003esk-\u003ex, pc-\u003esk-\u003exlen, pc-\u003esk-\u003ecurve);\n-}\n-\n-static size_t\n-se_do_sign(const br_ssl_server_policy_class **pctx,\n-\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n-{\n-\tbr_ssl_server_policy_ec_context *pc;\n-\tunsigned char hv[64];\n-\tconst br_hash_class *hc;\n-\n-\tpc \u003d (br_ssl_server_policy_ec_context *)pctx;\n-\thc \u003d br_multihash_getimpl(pc-\u003emhash, hash_id);\n-\tif (hc \u003d\u003d NULL) {\n-\t\treturn 0;\n-\t}\n-\tmemcpy(hv, data, hv_len);\n-\tif (len \u003c 139) {\n-\t\treturn 0;\n-\t}\n-\treturn pc-\u003eiecdsa(pc-\u003eiec, hc, hv, pc-\u003esk, data);\n-}\n-\n-static const br_ssl_server_policy_class se_policy_vtable \u003d {\n-\tsizeof(br_ssl_server_policy_ec_context),\n-\tse_choose,\n-\tse_do_keyx,\n-\tse_do_sign\n-};\n-\n-/* see bearssl_ssl.h */\n-void\n-br_ssl_server_set_single_ec(br_ssl_server_context *cc,\n-\tconst br_x509_certificate *chain, size_t chain_len,\n-\tconst br_ec_private_key *sk, unsigned allowed_usages,\n-\tunsigned cert_issuer_key_type,\n-\tconst br_ec_impl *iec, br_ecdsa_sign iecdsa)\n-{\n-\tcc-\u003echain_handler.single_ec.vtable \u003d \u0026se_policy_vtable;\n-\tcc-\u003echain_handler.single_ec.chain \u003d chain;\n-\tcc-\u003echain_handler.single_ec.chain_len \u003d chain_len;\n-\tcc-\u003echain_handler.single_ec.sk \u003d sk;\n-\tcc-\u003echain_handler.single_ec.allowed_usages \u003d allowed_usages;\n-\tcc-\u003echain_handler.single_ec.cert_issuer_key_type \u003d cert_issuer_key_type;\n-\tcc-\u003echain_handler.single_ec.mhash \u003d \u0026cc-\u003eeng.mhash;\n-\tcc-\u003echain_handler.single_ec.iec \u003d iec;\n-\tcc-\u003echain_handler.single_ec.iecdsa \u003d iecdsa;\n-\tcc-\u003epolicy_vtable \u003d \u0026cc-\u003echain_handler.single_ec.vtable;\n-}\ndiff --git a/src/ssl/ssl_single_rsa.c b/src/ssl/ssl_single_rsa.c\ndeleted file mode 100644\nindex 2ddbff9..0000000\n--- a/src/ssl/ssl_single_rsa.c\n+++ /dev/null\n@@ -1,158 +0,0 @@\n-/*\n- * Copyright (c) 2016 Thomas Pornin \u003cpornin@bolet.org\u003e\n- *\n- * Permission is hereby granted, free of charge, to any person obtaining \n- * a copy of this software and associated documentation files (the\n- * \u0022Software\u0022), to deal in the Software without restriction, including\n- * without limitation the rights to use, copy, modify, merge, publish,\n- * distribute, sublicense, and/or sell copies of the Software, and to\n- * permit persons to whom the Software is furnished to do so, subject to\n- * the following conditions:\n- *\n- * The above copyright notice and this permission notice shall be \n- * included in all copies or substantial portions of the Software.\n- *\n- * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, \n- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \n- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n- * SOFTWARE.\n- */\n-\n-#include \u0022inner.h\u0022\n-\n-static int\n-sr_choose(const br_ssl_server_policy_class **pctx,\n-\tconst br_ssl_server_context *cc,\n-\tbr_ssl_server_choices *choices)\n-{\n-\tbr_ssl_server_policy_rsa_context *pc;\n-\tconst br_suite_translated *st;\n-\tsize_t u, st_num;\n-\tint hash_id;\n-\n-\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n-\tst \u003d br_ssl_server_get_client_suites(cc, \u0026st_num);\n-\thash_id \u003d br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc));\n-\tif (cc-\u003eeng.session.version \u003c BR_TLS12) {\n-\t\thash_id \u003d 0;\n-\t}\n-\tchoices-\u003echain \u003d pc-\u003echain;\n-\tchoices-\u003echain_len \u003d pc-\u003echain_len;\n-\tfor (u \u003d 0; u \u003c st_num; u ++) {\n-\t\tunsigned tt;\n-\n-\t\ttt \u003d st[u][1];\n-\t\tswitch (tt \u003e\u003e 12) {\n-\t\tcase BR_SSLKEYX_RSA:\n-\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_KEYX) !\u003d 0) {\n-\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase BR_SSLKEYX_ECDHE_RSA:\n-\t\t\tif ((pc-\u003eallowed_usages \u0026 BR_KEYTYPE_SIGN) !\u003d 0\n-\t\t\t\t\u0026\u0026 hash_id !\u003d 0)\n-\t\t\t{\n-\t\t\t\tchoices-\u003ecipher_suite \u003d st[u][0];\n-\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-static uint32_t\n-sr_do_keyx(const br_ssl_server_policy_class **pctx,\n-\tunsigned char *data, size_t len)\n-{\n-\tbr_ssl_server_policy_rsa_context *pc;\n-\n-\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n-\treturn br_rsa_ssl_decrypt(pc-\u003eirsacore, pc-\u003esk, data, len);\n-}\n-\n-/*\n- * OID for hash functions in RSA signatures.\n- */\n-static const unsigned char HASH_OID_SHA1[] \u003d {\n-\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n-};\n-\n-static const unsigned char HASH_OID_SHA224[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n-};\n-\n-static const unsigned char HASH_OID_SHA256[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n-};\n-\n-static const unsigned char HASH_OID_SHA384[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n-};\n-\n-static const unsigned char HASH_OID_SHA512[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n-};\n-\n-static const unsigned char *HASH_OID[] \u003d {\n-\tHASH_OID_SHA1,\n-\tHASH_OID_SHA224,\n-\tHASH_OID_SHA256,\n-\tHASH_OID_SHA384,\n-\tHASH_OID_SHA512\n-};\n-\n-static size_t\n-sr_do_sign(const br_ssl_server_policy_class **pctx,\n-\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n-{\n-\tbr_ssl_server_policy_rsa_context *pc;\n-\tunsigned char hv[64];\n-\tsize_t sig_len;\n-\tconst unsigned char *hash_oid;\n-\n-\tpc \u003d (br_ssl_server_policy_rsa_context *)pctx;\n-\tmemcpy(hv, data, hv_len);\n-\tif (hash_id \u003d\u003d 0) {\n-\t\thash_oid \u003d NULL;\n-\t} else if (hash_id \u003e\u003d 2 \u0026\u0026 hash_id \u003c\u003d 6) {\n-\t\thash_oid \u003d HASH_OID[hash_id - 2];\n-\t} else {\n-\t\treturn 0;\n-\t}\n-\tsig_len \u003d (pc-\u003esk-\u003en_bitlen + 7) \u003e\u003e 3;\n-\tif (len \u003c sig_len) {\n-\t\treturn 0;\n-\t}\n-\treturn pc-\u003eirsasign(hash_oid, hv, hv_len, pc-\u003esk, data) ? sig_len : 0;\n-}\n-\n-static const br_ssl_server_policy_class sr_policy_vtable \u003d {\n-\tsizeof(br_ssl_server_policy_rsa_context),\n-\tsr_choose,\n-\tsr_do_keyx,\n-\tsr_do_sign\n-};\n-\n-/* see bearssl_ssl.h */\n-void\n-br_ssl_server_set_single_rsa(br_ssl_server_context *cc,\n-\tconst br_x509_certificate *chain, size_t chain_len,\n-\tconst br_rsa_private_key *sk, unsigned allowed_usages,\n-\tbr_rsa_private irsacore, br_rsa_pkcs1_sign irsasign)\n-{\n-\tcc-\u003echain_handler.single_rsa.vtable \u003d \u0026sr_policy_vtable;\n-\tcc-\u003echain_handler.single_rsa.chain \u003d chain;\n-\tcc-\u003echain_handler.single_rsa.chain_len \u003d chain_len;\n-\tcc-\u003echain_handler.single_rsa.sk \u003d sk;\n-\tcc-\u003echain_handler.single_rsa.allowed_usages \u003d allowed_usages;\n-\tcc-\u003echain_handler.single_rsa.irsacore \u003d irsacore;\n-\tcc-\u003echain_handler.single_rsa.irsasign \u003d irsasign;\n-\tcc-\u003epolicy_vtable \u003d \u0026cc-\u003echain_handler.single_rsa.vtable;\n-}\ndiff --git a/src/x509/x509_knownkey.c b/src/x509/x509_knownkey.c\nindex f00c32b..7674f3f 100644\n--- a/src/x509/x509_knownkey.c\n+++ b/src/x509/x509_knownkey.c\n@@ -27,29 +27,29 @@\n /* see bearssl_x509.h */\n void\n br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,\n-\tconst br_rsa_public_key *pk)\n+\tconst br_rsa_public_key *pk, unsigned usages)\n {\n \tctx-\u003evtable \u003d \u0026br_x509_knownkey_vtable;\n \tctx-\u003epkey.key_type \u003d BR_KEYTYPE_RSA;\n \tctx-\u003epkey.key.rsa \u003d *pk;\n+\tctx-\u003eusages \u003d usages;\n }\n \n /* see bearssl_x509.h */\n void\n br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,\n-\tconst br_ec_public_key *pk)\n+\tconst br_ec_public_key *pk, unsigned usages)\n {\n \tctx-\u003evtable \u003d \u0026br_x509_knownkey_vtable;\n \tctx-\u003epkey.key_type \u003d BR_KEYTYPE_EC;\n \tctx-\u003epkey.key.ec \u003d *pk;\n+\tctx-\u003eusages \u003d usages;\n }\n \n static void\n-kk_start_chain(const br_x509_class **ctx,\n-\tunsigned expected_key_type, const char *server_name)\n+kk_start_chain(const br_x509_class **ctx, const char *server_name)\n {\n \t(void)ctx;\n-\t(void)expected_key_type;\n \t(void)server_name;\n }\n \n@@ -82,9 +82,15 @@ kk_end_chain(const br_x509_class **ctx)\n }\n \n static const br_x509_pkey *\n-kk_get_pkey(const br_x509_class *const *ctx)\n+kk_get_pkey(const br_x509_class *const *ctx, unsigned *usages)\n {\n-\treturn \u0026((const br_x509_knownkey_context *)ctx)-\u003epkey;\n+\tconst br_x509_knownkey_context *xc;\n+\n+\txc \u003d (const br_x509_knownkey_context *)ctx;\n+\tif (usages !\u003d NULL) {\n+\t\t*usages \u003d xc-\u003eusages;\n+\t}\n+\treturn \u0026xc-\u003epkey;\n }\n \n /* see bearssl_x509.h */\ndiff --git a/src/x509/x509_minimal.c b/src/x509/x509_minimal.c\nindex 55d9e23..d022b00 100644\n--- a/src/x509/x509_minimal.c\n+++ b/src/x509/x509_minimal.c\n@@ -239,8 +239,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,\n }\n \n static void\n-xm_start_chain(const br_x509_class **ctx,\n-\tunsigned expected_key_type, const char *server_name)\n+xm_start_chain(const br_x509_class **ctx, const char *server_name)\n {\n \tbr_x509_minimal_context *cc;\n \n@@ -251,7 +250,6 @@ xm_start_chain(const br_x509_class **ctx,\n \tcc-\u003ecpu.dp \u003d cc-\u003edp_stack;\n \tcc-\u003ecpu.rp \u003d cc-\u003erp_stack;\n \tbr_x509_minimal_init_main(\u0026cc-\u003ecpu);\n-\tcc-\u003eexpected_key_type \u003d expected_key_type;\n \tif (server_name \u003d\u003d NULL || *server_name \u003d\u003d 0) {\n \t\tcc-\u003eserver_name \u003d NULL;\n \t} else {\n@@ -320,7 +318,7 @@ xm_end_chain(const br_x509_class **ctx)\n }\n \n static const br_x509_pkey *\n-xm_get_pkey(const br_x509_class *const *ctx)\n+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)\n {\n \tbr_x509_minimal_context *cc;\n \n@@ -328,6 +326,9 @@ xm_get_pkey(const br_x509_class *const *ctx)\n \tif (cc-\u003eerr \u003d\u003d BR_ERR_X509_OK\n \t\t|| cc-\u003eerr \u003d\u003d BR_ERR_X509_NOT_TRUSTED)\n \t{\n+\t\tif (usages !\u003d NULL) {\n+\t\t\t*usages \u003d cc-\u003ekey_usages;\n+\t\t}\n \t\treturn \u0026((br_x509_minimal_context *)ctx)-\u003epkey;\n \t} else {\n \t\treturn NULL;\n@@ -518,7 +519,6 @@ static const uint8_t t0_codeblock[] \u003d {\n \tT0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01,\n-\tT0_INT1(BR_ERR_X509_WRONG_KEY_TYPE), 0x00, 0x00, 0x01,\n \tT0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),\n \t0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00,\n \t0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00,\n@@ -527,182 +527,182 @@ static const uint8_t t0_codeblock[] \u003d {\n \t0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00,\n \t0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00,\n-\t0x01, T0_INT2(offsetof(CONTEXT_NAME, expected_key_type)), 0x00, 0x00,\n-\t0x01, T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01,\n+\t0x01, T0_INT2(offsetof(CONTEXT_NAME, key_usages)), 0x00, 0x00, 0x01,\n+\tT0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01,\n \tT0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01,\n \tT0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01,\n-\tT0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0x81, 0x31,\n-\t0x6E, 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00,\n+\tT0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0x81, 0x2F,\n+\t0x6C, 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00,\n \t0x00, 0x01, 0x81, 0x02, 0x00, 0x00, 0x01, 0x82, 0x08, 0x00, 0x00, 0x01,\n \t0x81, 0x70, 0x00, 0x00, 0x01, 0x81, 0x64, 0x00, 0x04, 0x03, 0x00, 0x03,\n \t0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07,\n \t0x02, 0x02, 0x02, 0x00, 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D,\n-\t0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x23, 0x02, 0x01, 0x13, 0x39, 0x02,\n-\t0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, 0x4F, 0x26, 0x00, 0x00, 0x06,\n-\t0x02, 0x50, 0x26, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x00, 0x11, 0x05,\n-\t0x02, 0x53, 0x26, 0x70, 0x00, 0x00, 0x11, 0x05, 0x02, 0x53, 0x26, 0x71,\n-\t0x00, 0x00, 0x06, 0x02, 0x49, 0x26, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00,\n-\t0x00, 0x23, 0x1E, 0x01, 0x08, 0x0E, 0x39, 0x3D, 0x1E, 0x09, 0x00, 0x09,\n-\t0x03, 0x00, 0x59, 0x29, 0x81, 0x1D, 0x37, 0x81, 0x1D, 0x81, 0x20, 0x23,\n-\t0x01, 0x20, 0x11, 0x06, 0x15, 0x22, 0x70, 0x81, 0x1B, 0x81, 0x20, 0x01,\n-\t0x02, 0x74, 0x81, 0x1E, 0x01, 0x02, 0x12, 0x06, 0x02, 0x54, 0x26, 0x75,\n-\t0x81, 0x20, 0x01, 0x02, 0x74, 0x81, 0x1C, 0x81, 0x1D, 0x81, 0x2A, 0x81,\n-\t0x10, 0x63, 0x5F, 0x1F, 0x16, 0x81, 0x1D, 0x81, 0x15, 0x27, 0x67, 0x06,\n-\t0x02, 0x48, 0x26, 0x81, 0x15, 0x27, 0x6E, 0x06, 0x02, 0x48, 0x26, 0x75,\n-\t0x81, 0x10, 0x02, 0x00, 0x06, 0x05, 0x2B, 0x03, 0x01, 0x04, 0x08, 0x5F,\n-\t0x66, 0x1F, 0x25, 0x05, 0x02, 0x47, 0x26, 0x66, 0x63, 0x1F, 0x16, 0x81,\n-\t0x1D, 0x81, 0x1D, 0x81, 0x11, 0x05, 0x02, 0x54, 0x26, 0x81, 0x24, 0x24,\n-\t0x06, 0x2C, 0x81, 0x2A, 0x81, 0x12, 0x81, 0x1D, 0x61, 0x81, 0x18, 0x03,\n-\t0x03, 0x61, 0x39, 0x02, 0x03, 0x09, 0x39, 0x02, 0x03, 0x0A, 0x81, 0x18,\n-\t0x03, 0x04, 0x75, 0x62, 0x28, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, 0x12,\n-\t0x06, 0x02, 0x55, 0x26, 0x75, 0x58, 0x03, 0x02, 0x04, 0x3E, 0x81, 0x01,\n-\t0x24, 0x06, 0x37, 0x81, 0x11, 0x05, 0x02, 0x54, 0x26, 0x68, 0x24, 0x06,\n-\t0x04, 0x01, 0x17, 0x04, 0x12, 0x69, 0x24, 0x06, 0x04, 0x01, 0x18, 0x04,\n-\t0x0A, 0x6A, 0x24, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x54, 0x26, 0x03,\n-\t0x05, 0x75, 0x81, 0x12, 0x23, 0x03, 0x06, 0x23, 0x61, 0x32, 0x0D, 0x06,\n-\t0x02, 0x4D, 0x26, 0x81, 0x13, 0x57, 0x03, 0x02, 0x04, 0x02, 0x54, 0x26,\n-\t0x75, 0x02, 0x00, 0x06, 0x33, 0x60, 0x2A, 0x01, 0x0F, 0x15, 0x23, 0x06,\n-\t0x09, 0x02, 0x02, 0x11, 0x05, 0x02, 0x56, 0x26, 0x04, 0x01, 0x22, 0x02,\n-\t0x02, 0x58, 0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02, 0x04, 0x1D,\n-\t0x04, 0x10, 0x57, 0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05, 0x02, 0x06,\n-\t0x1C, 0x04, 0x03, 0x54, 0x26, 0x22, 0x04, 0x24, 0x02, 0x02, 0x58, 0x2E,\n-\t0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02, 0x04, 0x21, 0x04, 0x10, 0x57,\n-\t0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05, 0x02, 0x06, 0x20, 0x04, 0x03,\n-\t0x54, 0x26, 0x22, 0x23, 0x06, 0x01, 0x26, 0x22, 0x01, 0x00, 0x03, 0x07,\n-\t0x81, 0x21, 0x01, 0x21, 0x81, 0x07, 0x01, 0x22, 0x81, 0x07, 0x23, 0x01,\n-\t0x23, 0x11, 0x06, 0x81, 0x36, 0x22, 0x70, 0x81, 0x1B, 0x81, 0x1D, 0x23,\n-\t0x06, 0x81, 0x28, 0x01, 0x00, 0x03, 0x08, 0x81, 0x1D, 0x81, 0x11, 0x22,\n-\t0x81, 0x20, 0x23, 0x01, 0x01, 0x11, 0x06, 0x06, 0x81, 0x14, 0x03, 0x08,\n-\t0x81, 0x20, 0x01, 0x04, 0x74, 0x81, 0x1B, 0x6D, 0x24, 0x06, 0x11, 0x02,\n-\t0x00, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x06, 0x81, 0x0E, 0x01, 0x7F, 0x03,\n-\t0x07, 0x04, 0x80, 0x72, 0x81, 0x09, 0x24, 0x06, 0x07, 0x02, 0x00, 0x81,\n-\t0x0F, 0x04, 0x80, 0x66, 0x81, 0x2D, 0x24, 0x06, 0x13, 0x02, 0x00, 0x06,\n-\t0x0A, 0x01, 0x00, 0x03, 0x01, 0x81, 0x0D, 0x03, 0x01, 0x04, 0x02, 0x81,\n-\t0x2B, 0x04, 0x80, 0x4E, 0x6C, 0x24, 0x06, 0x05, 0x81, 0x2B, 0x04, 0x80,\n-\t0x45, 0x81, 0x30, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x3C, 0x81, 0x08,\n-\t0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x33, 0x81, 0x2E, 0x24, 0x06, 0x04,\n-\t0x81, 0x2B, 0x04, 0x2A, 0x76, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x22,\n-\t0x81, 0x00, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x19, 0x6B, 0x24, 0x06,\n-\t0x04, 0x81, 0x2B, 0x04, 0x11, 0x81, 0x2F, 0x24, 0x06, 0x04, 0x81, 0x2B,\n-\t0x04, 0x08, 0x02, 0x08, 0x06, 0x02, 0x46, 0x26, 0x81, 0x2B, 0x75, 0x75,\n-\t0x04, 0xFE, 0x54, 0x75, 0x75, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02,\n-\t0x53, 0x26, 0x22, 0x75, 0x38, 0x02, 0x00, 0x06, 0x08, 0x02, 0x01, 0x3A,\n-\t0x2D, 0x05, 0x02, 0x42, 0x26, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00,\n-\t0x02, 0x07, 0x2D, 0x05, 0x02, 0x4E, 0x26, 0x81, 0x20, 0x72, 0x81, 0x1B,\n-\t0x81, 0x11, 0x06, 0x81, 0x07, 0x81, 0x25, 0x24, 0x06, 0x08, 0x01, 0x02,\n-\t0x58, 0x81, 0x02, 0x04, 0x80, 0x6C, 0x81, 0x26, 0x24, 0x06, 0x08, 0x01,\n-\t0x03, 0x58, 0x81, 0x03, 0x04, 0x80, 0x5F, 0x81, 0x27, 0x24, 0x06, 0x08,\n-\t0x01, 0x04, 0x58, 0x81, 0x04, 0x04, 0x80, 0x52, 0x81, 0x28, 0x24, 0x06,\n-\t0x08, 0x01, 0x05, 0x58, 0x81, 0x05, 0x04, 0x80, 0x45, 0x81, 0x29, 0x24,\n-\t0x06, 0x07, 0x01, 0x06, 0x58, 0x81, 0x06, 0x04, 0x39, 0x7B, 0x24, 0x06,\n-\t0x07, 0x01, 0x02, 0x57, 0x81, 0x02, 0x04, 0x2E, 0x7C, 0x24, 0x06, 0x07,\n-\t0x01, 0x03, 0x57, 0x81, 0x03, 0x04, 0x23, 0x7D, 0x24, 0x06, 0x07, 0x01,\n-\t0x04, 0x57, 0x81, 0x04, 0x04, 0x18, 0x7E, 0x24, 0x06, 0x07, 0x01, 0x05,\n-\t0x57, 0x81, 0x05, 0x04, 0x0D, 0x7F, 0x24, 0x06, 0x07, 0x01, 0x06, 0x57,\n-\t0x81, 0x06, 0x04, 0x02, 0x54, 0x26, 0x5C, 0x33, 0x5E, 0x35, 0x1B, 0x23,\n-\t0x05, 0x02, 0x54, 0x26, 0x5B, 0x35, 0x04, 0x02, 0x54, 0x26, 0x81, 0x2A,\n-\t0x81, 0x12, 0x23, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02,\n-\t0x4D, 0x26, 0x23, 0x5D, 0x33, 0x5A, 0x81, 0x13, 0x75, 0x75, 0x01, 0x00,\n-\t0x59, 0x34, 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x23, 0x01, 0x00, 0x01,\n-\t0x09, 0x6F, 0x05, 0x02, 0x45, 0x26, 0x00, 0x00, 0x2E, 0x2E, 0x00, 0x00,\n-\t0x01, 0x81, 0x08, 0x00, 0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81,\n-\t0x19, 0x00, 0x00, 0x01, 0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00,\n-\t0x00, 0x01, 0x82, 0x04, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01,\n-\t0x3D, 0x00, 0x00, 0x01, 0x80, 0x43, 0x00, 0x00, 0x01, 0x80, 0x4D, 0x00,\n-\t0x00, 0x01, 0x80, 0x57, 0x00, 0x00, 0x01, 0x80, 0x61, 0x00, 0x00, 0x2E,\n-\t0x11, 0x06, 0x07, 0x3F, 0x81, 0x1B, 0x81, 0x2A, 0x81, 0x21, 0x00, 0x00,\n-\t0x01, 0x81, 0x78, 0x00, 0x00, 0x01, 0x81, 0x68, 0x00, 0x00, 0x01, 0x7F,\n-\t0x78, 0x19, 0x01, 0x00, 0x78, 0x19, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x34,\n-\t0x00, 0x01, 0x7A, 0x0D, 0x06, 0x02, 0x4C, 0x26, 0x23, 0x03, 0x00, 0x0A,\n-\t0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x81, 0x1D, 0x23, 0x06,\n-\t0x18, 0x81, 0x20, 0x01, 0x22, 0x11, 0x06, 0x0C, 0x71, 0x81, 0x1F, 0x22,\n-\t0x2B, 0x02, 0x00, 0x2D, 0x03, 0x00, 0x04, 0x03, 0x22, 0x81, 0x1C, 0x04,\n-\t0x65, 0x75, 0x02, 0x00, 0x00, 0x00, 0x81, 0x1D, 0x81, 0x21, 0x23, 0x01,\n-\t0x01, 0x11, 0x06, 0x0A, 0x81, 0x14, 0x05, 0x02, 0x4E, 0x26, 0x81, 0x21,\n-\t0x04, 0x02, 0x4E, 0x26, 0x23, 0x01, 0x02, 0x11, 0x06, 0x0E, 0x22, 0x71,\n-\t0x81, 0x1E, 0x64, 0x29, 0x3E, 0x0D, 0x06, 0x02, 0x4E, 0x26, 0x81, 0x21,\n-\t0x01, 0x7F, 0x10, 0x06, 0x02, 0x53, 0x26, 0x22, 0x75, 0x00, 0x02, 0x06,\n-\t0x10, 0x60, 0x2A, 0x01, 0x10, 0x15, 0x06, 0x04, 0x01, 0x30, 0x04, 0x03,\n-\t0x01, 0x81, 0x40, 0x04, 0x02, 0x01, 0x04, 0x03, 0x00, 0x81, 0x20, 0x01,\n-\t0x03, 0x74, 0x81, 0x1B, 0x81, 0x22, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07,\n-\t0x12, 0x06, 0x02, 0x53, 0x26, 0x23, 0x01, 0x00, 0x2E, 0x11, 0x06, 0x05,\n-\t0x22, 0x4A, 0x26, 0x04, 0x17, 0x01, 0x01, 0x2E, 0x11, 0x06, 0x0B, 0x22,\n-\t0x81, 0x22, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E, 0x04, 0x06, 0x22, 0x81,\n-\t0x22, 0x01, 0x00, 0x22, 0x02, 0x00, 0x15, 0x05, 0x02, 0x4A, 0x26, 0x81,\n-\t0x2A, 0x00, 0x02, 0x36, 0x01, 0x00, 0x65, 0x35, 0x81, 0x1D, 0x23, 0x06,\n-\t0x80, 0x6F, 0x81, 0x20, 0x01, 0x11, 0x73, 0x81, 0x1B, 0x23, 0x05, 0x02,\n-\t0x41, 0x26, 0x23, 0x06, 0x80, 0x5B, 0x81, 0x1D, 0x81, 0x20, 0x01, 0x06,\n-\t0x74, 0x81, 0x1B, 0x23, 0x01, 0x03, 0x11, 0x06, 0x1E, 0x81, 0x22, 0x01,\n-\t0x10, 0x0E, 0x03, 0x00, 0x81, 0x22, 0x01, 0x08, 0x0E, 0x02, 0x00, 0x09,\n-\t0x03, 0x00, 0x81, 0x22, 0x02, 0x00, 0x09, 0x01, 0x82, 0xD4, 0x88, 0x03,\n-\t0x11, 0x03, 0x01, 0x81, 0x2A, 0x02, 0x01, 0x06, 0x23, 0x81, 0x20, 0x23,\n-\t0x23, 0x01, 0x0C, 0x11, 0x39, 0x01, 0x13, 0x11, 0x2D, 0x39, 0x01, 0x14,\n-\t0x11, 0x2D, 0x06, 0x07, 0x71, 0x81, 0x1F, 0x22, 0x75, 0x04, 0x07, 0x22,\n-\t0x01, 0x00, 0x65, 0x35, 0x81, 0x2A, 0x04, 0x02, 0x81, 0x2A, 0x04, 0xFF,\n-\t0x21, 0x75, 0x04, 0xFF, 0x0D, 0x75, 0x1A, 0x00, 0x00, 0x81, 0x20, 0x01,\n-\t0x06, 0x74, 0x81, 0x1F, 0x00, 0x00, 0x81, 0x20, 0x01, 0x03, 0x74, 0x81,\n-\t0x1B, 0x81, 0x22, 0x06, 0x02, 0x52, 0x26, 0x00, 0x00, 0x39, 0x23, 0x06,\n-\t0x07, 0x2F, 0x23, 0x06, 0x01, 0x19, 0x04, 0x76, 0x3F, 0x00, 0x00, 0x01,\n-\t0x01, 0x74, 0x81, 0x1A, 0x01, 0x01, 0x10, 0x06, 0x02, 0x40, 0x26, 0x81,\n-\t0x22, 0x3B, 0x00, 0x04, 0x81, 0x20, 0x23, 0x01, 0x17, 0x01, 0x18, 0x6F,\n-\t0x05, 0x02, 0x45, 0x26, 0x01, 0x18, 0x11, 0x03, 0x00, 0x71, 0x81, 0x1B,\n-\t0x81, 0x16, 0x02, 0x00, 0x06, 0x0D, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01,\n-\t0x81, 0x16, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x23, 0x01, 0x32, 0x0D, 0x06,\n-\t0x04, 0x01, 0x80, 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02,\n-\t0x01, 0x01, 0x82, 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04,\n-\t0x0C, 0x09, 0x02, 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C,\n-\t0x0A, 0x02, 0x01, 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09,\n-\t0x03, 0x03, 0x01, 0x01, 0x01, 0x0C, 0x81, 0x17, 0x3E, 0x01, 0x01, 0x0E,\n-\t0x02, 0x01, 0x01, 0x04, 0x07, 0x3C, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07,\n-\t0x3B, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3C, 0x2D, 0x15, 0x06, 0x03,\n-\t0x01, 0x18, 0x09, 0x81, 0x0B, 0x09, 0x77, 0x23, 0x01, 0x05, 0x14, 0x02,\n-\t0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x39, 0x81, 0x17,\n-\t0x02, 0x03, 0x09, 0x3E, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0x81, 0x17,\n-\t0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0x81, 0x17,\n-\t0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C,\n-\t0x81, 0x17, 0x02, 0x02, 0x09, 0x03, 0x02, 0x81, 0x22, 0x23, 0x01, 0x2E,\n-\t0x11, 0x06, 0x0E, 0x22, 0x81, 0x22, 0x23, 0x01, 0x30, 0x01, 0x39, 0x6F,\n-\t0x06, 0x03, 0x22, 0x04, 0x73, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x45,\n-\t0x26, 0x75, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0x81, 0x22, 0x79, 0x01,\n-\t0x0A, 0x08, 0x03, 0x00, 0x81, 0x22, 0x79, 0x02, 0x00, 0x09, 0x00, 0x02,\n-\t0x03, 0x00, 0x03, 0x01, 0x81, 0x16, 0x23, 0x02, 0x01, 0x02, 0x00, 0x6F,\n-\t0x05, 0x02, 0x45, 0x26, 0x00, 0x00, 0x32, 0x81, 0x20, 0x01, 0x02, 0x74,\n-\t0x0B, 0x81, 0x19, 0x00, 0x03, 0x23, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,\n-\t0x81, 0x1B, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x51,\n-\t0x26, 0x23, 0x01, 0x00, 0x11, 0x06, 0x0C, 0x22, 0x23, 0x05, 0x04, 0x22,\n-\t0x01, 0x00, 0x00, 0x81, 0x22, 0x04, 0x6E, 0x02, 0x01, 0x23, 0x05, 0x02,\n-\t0x4D, 0x26, 0x3E, 0x03, 0x01, 0x02, 0x02, 0x35, 0x02, 0x02, 0x3D, 0x03,\n-\t0x02, 0x23, 0x06, 0x04, 0x81, 0x22, 0x04, 0x67, 0x22, 0x02, 0x00, 0x02,\n-\t0x01, 0x0A, 0x00, 0x01, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x0D, 0x06,\n-\t0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x23, 0x05, 0x02, 0x4B, 0x26, 0x03,\n-\t0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x1A, 0x02, 0x00,\n-\t0x3E, 0x03, 0x00, 0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02,\n-\t0x4C, 0x26, 0x01, 0x08, 0x0E, 0x39, 0x81, 0x22, 0x32, 0x09, 0x04, 0x5F,\n-\t0x00, 0x00, 0x81, 0x1A, 0x81, 0x0C, 0x00, 0x00, 0x81, 0x1B, 0x81, 0x2A,\n-\t0x00, 0x00, 0x81, 0x20, 0x72, 0x81, 0x1B, 0x00, 0x01, 0x81, 0x1B, 0x23,\n-\t0x05, 0x02, 0x51, 0x26, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06,\n-\t0x02, 0x51, 0x26, 0x03, 0x00, 0x23, 0x06, 0x17, 0x81, 0x22, 0x02, 0x00,\n-\t0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x51, 0x26, 0x01,\n-\t0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x66, 0x22, 0x02, 0x00, 0x00, 0x00,\n-\t0x81, 0x1B, 0x23, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x09, 0x81, 0x2A, 0x01,\n-\t0x00, 0x65, 0x35, 0x01, 0x00, 0x00, 0x23, 0x65, 0x35, 0x65, 0x3D, 0x81,\n-\t0x13, 0x01, 0x7F, 0x00, 0x01, 0x81, 0x22, 0x03, 0x00, 0x02, 0x00, 0x01,\n-\t0x05, 0x14, 0x01, 0x01, 0x15, 0x2C, 0x02, 0x00, 0x01, 0x06, 0x14, 0x23,\n-\t0x01, 0x01, 0x15, 0x06, 0x02, 0x43, 0x26, 0x01, 0x04, 0x0E, 0x02, 0x00,\n-\t0x01, 0x1F, 0x15, 0x23, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x44, 0x26, 0x09,\n-\t0x00, 0x00, 0x23, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x81, 0x20,\n-\t0x00, 0x00, 0x23, 0x05, 0x02, 0x4C, 0x26, 0x3E, 0x81, 0x23, 0x00, 0x00,\n-\t0x30, 0x23, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x22, 0x19, 0x04, 0x74,\n-\t0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00,\n-\t0x00, 0x01, 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00,\n-\t0x00, 0x81, 0x2B, 0x22, 0x00, 0x00, 0x23, 0x06, 0x08, 0x81, 0x2C, 0x23,\n-\t0x06, 0x01, 0x19, 0x04, 0x75, 0x00, 0x00, 0x01, 0x00, 0x2E, 0x2F, 0x0B,\n-\t0x3F, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x01, 0x81, 0x7C, 0x00,\n-\t0x00, 0x01, 0x82, 0x11, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x01,\n-\t0x03, 0x31, 0x01, 0x03, 0x31, 0x00\n+\t0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x23, 0x02, 0x01, 0x13, 0x38, 0x02,\n+\t0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, 0x4E, 0x26, 0x00, 0x00, 0x06,\n+\t0x02, 0x4F, 0x26, 0x00, 0x00, 0x01, 0x10, 0x71, 0x00, 0x00, 0x11, 0x05,\n+\t0x02, 0x52, 0x26, 0x6E, 0x00, 0x00, 0x11, 0x05, 0x02, 0x52, 0x26, 0x6F,\n+\t0x00, 0x00, 0x06, 0x02, 0x48, 0x26, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00,\n+\t0x00, 0x23, 0x1E, 0x01, 0x08, 0x0E, 0x38, 0x3C, 0x1E, 0x09, 0x00, 0x09,\n+\t0x03, 0x00, 0x57, 0x29, 0x81, 0x1B, 0x36, 0x81, 0x1B, 0x81, 0x1E, 0x23,\n+\t0x01, 0x20, 0x11, 0x06, 0x15, 0x22, 0x6E, 0x81, 0x19, 0x81, 0x1E, 0x01,\n+\t0x02, 0x72, 0x81, 0x1C, 0x01, 0x02, 0x12, 0x06, 0x02, 0x53, 0x26, 0x73,\n+\t0x81, 0x1E, 0x01, 0x02, 0x72, 0x81, 0x1A, 0x81, 0x1B, 0x81, 0x28, 0x81,\n+\t0x0E, 0x61, 0x5D, 0x1F, 0x16, 0x81, 0x1B, 0x81, 0x13, 0x27, 0x65, 0x06,\n+\t0x02, 0x47, 0x26, 0x81, 0x13, 0x27, 0x6C, 0x06, 0x02, 0x47, 0x26, 0x73,\n+\t0x81, 0x0E, 0x02, 0x00, 0x06, 0x05, 0x2A, 0x03, 0x01, 0x04, 0x08, 0x5D,\n+\t0x64, 0x1F, 0x25, 0x05, 0x02, 0x46, 0x26, 0x64, 0x61, 0x1F, 0x16, 0x81,\n+\t0x1B, 0x81, 0x1B, 0x81, 0x0F, 0x05, 0x02, 0x53, 0x26, 0x81, 0x22, 0x24,\n+\t0x06, 0x2C, 0x81, 0x28, 0x81, 0x10, 0x81, 0x1B, 0x5F, 0x81, 0x16, 0x03,\n+\t0x03, 0x5F, 0x38, 0x02, 0x03, 0x09, 0x38, 0x02, 0x03, 0x0A, 0x81, 0x16,\n+\t0x03, 0x04, 0x73, 0x60, 0x28, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, 0x12,\n+\t0x06, 0x02, 0x54, 0x26, 0x73, 0x56, 0x03, 0x02, 0x04, 0x3D, 0x7F, 0x24,\n+\t0x06, 0x37, 0x81, 0x0F, 0x05, 0x02, 0x53, 0x26, 0x66, 0x24, 0x06, 0x04,\n+\t0x01, 0x17, 0x04, 0x12, 0x67, 0x24, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A,\n+\t0x68, 0x24, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x53, 0x26, 0x03, 0x05,\n+\t0x73, 0x81, 0x10, 0x23, 0x03, 0x06, 0x23, 0x5F, 0x31, 0x0D, 0x06, 0x02,\n+\t0x4C, 0x26, 0x81, 0x11, 0x55, 0x03, 0x02, 0x04, 0x02, 0x53, 0x26, 0x73,\n+\t0x02, 0x00, 0x06, 0x21, 0x02, 0x02, 0x56, 0x2D, 0x11, 0x06, 0x08, 0x22,\n+\t0x02, 0x03, 0x02, 0x04, 0x1D, 0x04, 0x10, 0x55, 0x2D, 0x11, 0x06, 0x08,\n+\t0x22, 0x02, 0x05, 0x02, 0x06, 0x1C, 0x04, 0x03, 0x53, 0x26, 0x22, 0x04,\n+\t0x24, 0x02, 0x02, 0x56, 0x2D, 0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02,\n+\t0x04, 0x21, 0x04, 0x10, 0x55, 0x2D, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05,\n+\t0x02, 0x06, 0x20, 0x04, 0x03, 0x53, 0x26, 0x22, 0x23, 0x06, 0x01, 0x26,\n+\t0x22, 0x01, 0x00, 0x03, 0x07, 0x81, 0x1F, 0x01, 0x21, 0x81, 0x05, 0x01,\n+\t0x22, 0x81, 0x05, 0x23, 0x01, 0x23, 0x11, 0x06, 0x81, 0x35, 0x22, 0x6E,\n+\t0x81, 0x19, 0x81, 0x1B, 0x23, 0x06, 0x81, 0x27, 0x01, 0x00, 0x03, 0x08,\n+\t0x81, 0x1B, 0x81, 0x0F, 0x22, 0x81, 0x1E, 0x23, 0x01, 0x01, 0x11, 0x06,\n+\t0x06, 0x81, 0x12, 0x03, 0x08, 0x81, 0x1E, 0x01, 0x04, 0x72, 0x81, 0x19,\n+\t0x6B, 0x24, 0x06, 0x11, 0x02, 0x00, 0x06, 0x04, 0x81, 0x29, 0x04, 0x06,\n+\t0x81, 0x0C, 0x01, 0x7F, 0x03, 0x07, 0x04, 0x80, 0x71, 0x81, 0x07, 0x24,\n+\t0x06, 0x07, 0x02, 0x00, 0x81, 0x0D, 0x04, 0x80, 0x65, 0x81, 0x2B, 0x24,\n+\t0x06, 0x13, 0x02, 0x00, 0x06, 0x0A, 0x01, 0x00, 0x03, 0x01, 0x81, 0x0B,\n+\t0x03, 0x01, 0x04, 0x02, 0x81, 0x29, 0x04, 0x80, 0x4D, 0x6A, 0x24, 0x06,\n+\t0x05, 0x81, 0x29, 0x04, 0x80, 0x44, 0x81, 0x2E, 0x24, 0x06, 0x04, 0x81,\n+\t0x29, 0x04, 0x3B, 0x81, 0x06, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x32,\n+\t0x81, 0x2C, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x29, 0x74, 0x24, 0x06,\n+\t0x04, 0x81, 0x29, 0x04, 0x21, 0x7E, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04,\n+\t0x19, 0x69, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x11, 0x81, 0x2D, 0x24,\n+\t0x06, 0x04, 0x81, 0x29, 0x04, 0x08, 0x02, 0x08, 0x06, 0x02, 0x45, 0x26,\n+\t0x81, 0x29, 0x73, 0x73, 0x04, 0xFE, 0x55, 0x73, 0x73, 0x04, 0x08, 0x01,\n+\t0x7F, 0x11, 0x05, 0x02, 0x52, 0x26, 0x22, 0x73, 0x37, 0x02, 0x00, 0x06,\n+\t0x08, 0x02, 0x01, 0x39, 0x2C, 0x05, 0x02, 0x41, 0x26, 0x02, 0x00, 0x06,\n+\t0x01, 0x17, 0x02, 0x00, 0x02, 0x07, 0x2C, 0x05, 0x02, 0x4D, 0x26, 0x81,\n+\t0x1E, 0x70, 0x81, 0x19, 0x81, 0x0F, 0x06, 0x81, 0x07, 0x81, 0x23, 0x24,\n+\t0x06, 0x08, 0x01, 0x02, 0x56, 0x81, 0x00, 0x04, 0x80, 0x6C, 0x81, 0x24,\n+\t0x24, 0x06, 0x08, 0x01, 0x03, 0x56, 0x81, 0x01, 0x04, 0x80, 0x5F, 0x81,\n+\t0x25, 0x24, 0x06, 0x08, 0x01, 0x04, 0x56, 0x81, 0x02, 0x04, 0x80, 0x52,\n+\t0x81, 0x26, 0x24, 0x06, 0x08, 0x01, 0x05, 0x56, 0x81, 0x03, 0x04, 0x80,\n+\t0x45, 0x81, 0x27, 0x24, 0x06, 0x07, 0x01, 0x06, 0x56, 0x81, 0x04, 0x04,\n+\t0x39, 0x79, 0x24, 0x06, 0x07, 0x01, 0x02, 0x55, 0x81, 0x00, 0x04, 0x2E,\n+\t0x7A, 0x24, 0x06, 0x07, 0x01, 0x03, 0x55, 0x81, 0x01, 0x04, 0x23, 0x7B,\n+\t0x24, 0x06, 0x07, 0x01, 0x04, 0x55, 0x81, 0x02, 0x04, 0x18, 0x7C, 0x24,\n+\t0x06, 0x07, 0x01, 0x05, 0x55, 0x81, 0x03, 0x04, 0x0D, 0x7D, 0x24, 0x06,\n+\t0x07, 0x01, 0x06, 0x55, 0x81, 0x04, 0x04, 0x02, 0x53, 0x26, 0x5A, 0x32,\n+\t0x5C, 0x34, 0x1B, 0x23, 0x05, 0x02, 0x53, 0x26, 0x59, 0x34, 0x04, 0x02,\n+\t0x53, 0x26, 0x81, 0x28, 0x81, 0x10, 0x23, 0x01,\n+\tT0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x4C, 0x26, 0x23, 0x5B,\n+\t0x32, 0x58, 0x81, 0x11, 0x73, 0x73, 0x01, 0x00, 0x57, 0x33, 0x18, 0x00,\n+\t0x00, 0x01, 0x30, 0x0A, 0x23, 0x01, 0x00, 0x01, 0x09, 0x6D, 0x05, 0x02,\n+\t0x44, 0x26, 0x00, 0x00, 0x2D, 0x2D, 0x00, 0x00, 0x01, 0x81, 0x08, 0x00,\n+\t0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81, 0x19, 0x00, 0x00, 0x01,\n+\t0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00, 0x00, 0x01, 0x82, 0x04,\n+\t0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00, 0x01,\n+\t0x80, 0x43, 0x00, 0x00, 0x01, 0x80, 0x4D, 0x00, 0x00, 0x01, 0x80, 0x57,\n+\t0x00, 0x00, 0x01, 0x80, 0x61, 0x00, 0x00, 0x2D, 0x11, 0x06, 0x07, 0x3E,\n+\t0x81, 0x19, 0x81, 0x28, 0x81, 0x1F, 0x00, 0x00, 0x01, 0x81, 0x78, 0x00,\n+\t0x00, 0x01, 0x81, 0x68, 0x00, 0x00, 0x01, 0x30, 0x5E, 0x34, 0x01, 0x7F,\n+\t0x76, 0x19, 0x01, 0x00, 0x76, 0x19, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x34,\n+\t0x00, 0x01, 0x78, 0x0D, 0x06, 0x02, 0x4B, 0x26, 0x23, 0x03, 0x00, 0x0A,\n+\t0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x81, 0x1B, 0x23, 0x06,\n+\t0x18, 0x81, 0x1E, 0x01, 0x22, 0x11, 0x06, 0x0C, 0x6F, 0x81, 0x1D, 0x22,\n+\t0x2A, 0x02, 0x00, 0x2C, 0x03, 0x00, 0x04, 0x03, 0x22, 0x81, 0x1A, 0x04,\n+\t0x65, 0x73, 0x02, 0x00, 0x00, 0x00, 0x81, 0x1B, 0x81, 0x1F, 0x23, 0x01,\n+\t0x01, 0x11, 0x06, 0x0A, 0x81, 0x12, 0x05, 0x02, 0x4D, 0x26, 0x81, 0x1F,\n+\t0x04, 0x02, 0x4D, 0x26, 0x23, 0x01, 0x02, 0x11, 0x06, 0x0E, 0x22, 0x6F,\n+\t0x81, 0x1C, 0x62, 0x29, 0x3D, 0x0D, 0x06, 0x02, 0x4D, 0x26, 0x81, 0x1F,\n+\t0x01, 0x7F, 0x10, 0x06, 0x02, 0x52, 0x26, 0x22, 0x73, 0x00, 0x02, 0x03,\n+\t0x00, 0x81, 0x1E, 0x01, 0x03, 0x72, 0x81, 0x19, 0x81, 0x20, 0x03, 0x01,\n+\t0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02, 0x52, 0x26, 0x23, 0x01, 0x00,\n+\t0x2D, 0x11, 0x06, 0x05, 0x22, 0x49, 0x26, 0x04, 0x17, 0x01, 0x01, 0x2D,\n+\t0x11, 0x06, 0x0B, 0x22, 0x81, 0x20, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E,\n+\t0x04, 0x06, 0x22, 0x81, 0x20, 0x01, 0x00, 0x22, 0x02, 0x00, 0x06, 0x19,\n+\t0x01, 0x00, 0x2D, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01, 0x10, 0x2C, 0x38,\n+\t0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2C, 0x5E, 0x34, 0x04,\n+\t0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x49, 0x26, 0x81, 0x28, 0x00, 0x02,\n+\t0x35, 0x01, 0x00, 0x63, 0x34, 0x81, 0x1B, 0x23, 0x06, 0x80, 0x6F, 0x81,\n+\t0x1E, 0x01, 0x11, 0x71, 0x81, 0x19, 0x23, 0x05, 0x02, 0x40, 0x26, 0x23,\n+\t0x06, 0x80, 0x5B, 0x81, 0x1B, 0x81, 0x1E, 0x01, 0x06, 0x72, 0x81, 0x19,\n+\t0x23, 0x01, 0x03, 0x11, 0x06, 0x1E, 0x81, 0x20, 0x01, 0x10, 0x0E, 0x03,\n+\t0x00, 0x81, 0x20, 0x01, 0x08, 0x0E, 0x02, 0x00, 0x09, 0x03, 0x00, 0x81,\n+\t0x20, 0x02, 0x00, 0x09, 0x01, 0x82, 0xD4, 0x88, 0x03, 0x11, 0x03, 0x01,\n+\t0x81, 0x28, 0x02, 0x01, 0x06, 0x23, 0x81, 0x1E, 0x23, 0x23, 0x01, 0x0C,\n+\t0x11, 0x38, 0x01, 0x13, 0x11, 0x2C, 0x38, 0x01, 0x14, 0x11, 0x2C, 0x06,\n+\t0x07, 0x6F, 0x81, 0x1D, 0x22, 0x73, 0x04, 0x07, 0x22, 0x01, 0x00, 0x63,\n+\t0x34, 0x81, 0x28, 0x04, 0x02, 0x81, 0x28, 0x04, 0xFF, 0x21, 0x73, 0x04,\n+\t0xFF, 0x0D, 0x73, 0x1A, 0x00, 0x00, 0x81, 0x1E, 0x01, 0x06, 0x72, 0x81,\n+\t0x1D, 0x00, 0x00, 0x81, 0x1E, 0x01, 0x03, 0x72, 0x81, 0x19, 0x81, 0x20,\n+\t0x06, 0x02, 0x51, 0x26, 0x00, 0x00, 0x38, 0x23, 0x06, 0x07, 0x2E, 0x23,\n+\t0x06, 0x01, 0x19, 0x04, 0x76, 0x3E, 0x00, 0x00, 0x01, 0x01, 0x72, 0x81,\n+\t0x18, 0x01, 0x01, 0x10, 0x06, 0x02, 0x3F, 0x26, 0x81, 0x20, 0x3A, 0x00,\n+\t0x04, 0x81, 0x1E, 0x23, 0x01, 0x17, 0x01, 0x18, 0x6D, 0x05, 0x02, 0x44,\n+\t0x26, 0x01, 0x18, 0x11, 0x03, 0x00, 0x6F, 0x81, 0x19, 0x81, 0x14, 0x02,\n+\t0x00, 0x06, 0x0D, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0x81, 0x14, 0x02,\n+\t0x01, 0x09, 0x04, 0x0E, 0x23, 0x01, 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80,\n+\t0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02, 0x01, 0x01, 0x82,\n+\t0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02,\n+\t0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01,\n+\t0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01,\n+\t0x01, 0x01, 0x0C, 0x81, 0x15, 0x3D, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01,\n+\t0x04, 0x07, 0x3B, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x3A, 0x02, 0x01,\n+\t0x01, 0x83, 0x10, 0x07, 0x3B, 0x2C, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09,\n+\t0x81, 0x09, 0x09, 0x75, 0x23, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03,\n+\t0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x38, 0x81, 0x15, 0x02, 0x03, 0x09,\n+\t0x3D, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0x81, 0x15, 0x01, 0x9C, 0x10,\n+\t0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0x81, 0x15, 0x01, 0x3C, 0x08,\n+\t0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0x81, 0x15, 0x02,\n+\t0x02, 0x09, 0x03, 0x02, 0x81, 0x20, 0x23, 0x01, 0x2E, 0x11, 0x06, 0x0E,\n+\t0x22, 0x81, 0x20, 0x23, 0x01, 0x30, 0x01, 0x39, 0x6D, 0x06, 0x03, 0x22,\n+\t0x04, 0x73, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x44, 0x26, 0x73, 0x02,\n+\t0x03, 0x02, 0x02, 0x00, 0x01, 0x81, 0x20, 0x77, 0x01, 0x0A, 0x08, 0x03,\n+\t0x00, 0x81, 0x20, 0x77, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03,\n+\t0x01, 0x81, 0x14, 0x23, 0x02, 0x01, 0x02, 0x00, 0x6D, 0x05, 0x02, 0x44,\n+\t0x26, 0x00, 0x00, 0x31, 0x81, 0x1E, 0x01, 0x02, 0x72, 0x0B, 0x81, 0x17,\n+\t0x00, 0x03, 0x23, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x81, 0x19, 0x81,\n+\t0x20, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x50, 0x26, 0x23, 0x01,\n+\t0x00, 0x11, 0x06, 0x0C, 0x22, 0x23, 0x05, 0x04, 0x22, 0x01, 0x00, 0x00,\n+\t0x81, 0x20, 0x04, 0x6E, 0x02, 0x01, 0x23, 0x05, 0x02, 0x4C, 0x26, 0x3D,\n+\t0x03, 0x01, 0x02, 0x02, 0x34, 0x02, 0x02, 0x3C, 0x03, 0x02, 0x23, 0x06,\n+\t0x04, 0x81, 0x20, 0x04, 0x67, 0x22, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00,\n+\t0x01, 0x81, 0x20, 0x23, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01,\n+\t0x81, 0x00, 0x0A, 0x23, 0x05, 0x02, 0x4A, 0x26, 0x03, 0x00, 0x01, 0x00,\n+\t0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x1A, 0x02, 0x00, 0x3D, 0x03, 0x00,\n+\t0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4B, 0x26, 0x01,\n+\t0x08, 0x0E, 0x38, 0x81, 0x20, 0x31, 0x09, 0x04, 0x5F, 0x00, 0x00, 0x81,\n+\t0x18, 0x81, 0x0A, 0x00, 0x00, 0x81, 0x19, 0x81, 0x28, 0x00, 0x00, 0x81,\n+\t0x1E, 0x70, 0x81, 0x19, 0x00, 0x01, 0x81, 0x19, 0x23, 0x05, 0x02, 0x50,\n+\t0x26, 0x81, 0x20, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x50, 0x26,\n+\t0x03, 0x00, 0x23, 0x06, 0x17, 0x81, 0x20, 0x02, 0x00, 0x23, 0x01, 0x87,\n+\t0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x50, 0x26, 0x01, 0x08, 0x0E, 0x09,\n+\t0x03, 0x00, 0x04, 0x66, 0x22, 0x02, 0x00, 0x00, 0x00, 0x81, 0x19, 0x23,\n+\t0x01, 0x81, 0x7F, 0x12, 0x06, 0x09, 0x81, 0x28, 0x01, 0x00, 0x63, 0x34,\n+\t0x01, 0x00, 0x00, 0x23, 0x63, 0x34, 0x63, 0x3C, 0x81, 0x11, 0x01, 0x7F,\n+\t0x00, 0x01, 0x81, 0x20, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05, 0x14, 0x01,\n+\t0x01, 0x15, 0x2B, 0x02, 0x00, 0x01, 0x06, 0x14, 0x23, 0x01, 0x01, 0x15,\n+\t0x06, 0x02, 0x42, 0x26, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01, 0x1F, 0x15,\n+\t0x23, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x43, 0x26, 0x09, 0x00, 0x00, 0x23,\n+\t0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x81, 0x1E, 0x00, 0x00, 0x23,\n+\t0x05, 0x02, 0x4B, 0x26, 0x3D, 0x81, 0x21, 0x00, 0x00, 0x2F, 0x23, 0x01,\n+\t0x00, 0x13, 0x06, 0x01, 0x00, 0x22, 0x19, 0x04, 0x74, 0x00, 0x01, 0x01,\n+\t0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x1F,\n+\t0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x81, 0x29,\n+\t0x22, 0x00, 0x00, 0x23, 0x06, 0x08, 0x81, 0x2A, 0x23, 0x06, 0x01, 0x19,\n+\t0x04, 0x75, 0x00, 0x00, 0x01, 0x00, 0x2D, 0x2E, 0x0B, 0x3E, 0x00, 0x00,\n+\t0x01, 0x81, 0x6C, 0x00, 0x00, 0x01, 0x81, 0x7C, 0x00, 0x00, 0x01, 0x82,\n+\t0x11, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x01, 0x03, 0x30, 0x01,\n+\t0x03, 0x30, 0x00\n };\n \n static const uint16_t t0_caddr[] \u003d {\n@@ -736,98 +736,97 @@ static const uint16_t t0_caddr[] \u003d {\n \t112,\n \t116,\n \t120,\n-\t124,\n-\t129,\n-\t134,\n-\t139,\n-\t144,\n-\t149,\n-\t154,\n-\t159,\n-\t164,\n-\t172,\n-\t177,\n-\t182,\n-\t187,\n-\t192,\n-\t197,\n-\t202,\n-\t207,\n-\t212,\n-\t217,\n-\t222,\n-\t227,\n-\t232,\n-\t261,\n-\t276,\n-\t282,\n-\t288,\n-\t293,\n-\t301,\n-\t309,\n-\t315,\n-\t320,\n-\t331,\n+\t125,\n+\t130,\n+\t135,\n+\t140,\n+\t145,\n+\t150,\n+\t155,\n+\t160,\n+\t168,\n+\t173,\n+\t178,\n+\t183,\n+\t188,\n+\t193,\n+\t198,\n+\t203,\n+\t208,\n+\t213,\n+\t218,\n+\t223,\n+\t228,\n+\t257,\n+\t272,\n+\t278,\n+\t284,\n+\t289,\n+\t297,\n+\t305,\n+\t311,\n+\t316,\n+\t327,\n+\t1029,\n+\t1044,\n+\t1048,\n \t1053,\n+\t1058,\n+\t1063,\n \t1068,\n-\t1072,\n-\t1077,\n-\t1082,\n+\t1073,\n+\t1078,\n+\t1083,\n \t1087,\n \t1092,\n \t1097,\n \t1102,\n \t1107,\n-\t1111,\n-\t1116,\n-\t1121,\n-\t1126,\n-\t1131,\n-\t1144,\n-\t1149,\n-\t1154,\n-\t1165,\n-\t1170,\n-\t1184,\n-\t1222,\n-\t1275,\n-\t1363,\n-\t1489,\n-\t1498,\n-\t1513,\n-\t1527,\n-\t1544,\n-\t1776,\n-\t1792,\n+\t1120,\n+\t1125,\n+\t1130,\n+\t1145,\n+\t1150,\n+\t1164,\n+\t1202,\n+\t1255,\n+\t1352,\n+\t1478,\n+\t1487,\n+\t1502,\n+\t1516,\n+\t1533,\n+\t1765,\n+\t1781,\n+\t1799,\n \t1810,\n-\t1821,\n-\t1892,\n-\t1950,\n-\t1956,\n-\t1962,\n-\t1969,\n-\t2020,\n-\t2049,\n-\t2094,\n-\t2106,\n-\t2116,\n-\t2129,\n-\t2133,\n-\t2137,\n-\t2141,\n-\t2145,\n-\t2149,\n-\t2153,\n-\t2158,\n-\t2171,\n-\t2179,\n-\t2184,\n-\t2189,\n-\t2194,\n-\t2199\n+\t1881,\n+\t1939,\n+\t1945,\n+\t1951,\n+\t1958,\n+\t2009,\n+\t2038,\n+\t2083,\n+\t2095,\n+\t2105,\n+\t2118,\n+\t2122,\n+\t2126,\n+\t2130,\n+\t2134,\n+\t2138,\n+\t2142,\n+\t2147,\n+\t2160,\n+\t2168,\n+\t2173,\n+\t2178,\n+\t2183,\n+\t2188\n };\n \n-#define T0_INTERPRETED 59\n+#define T0_INTERPRETED 58\n \n #define T0_ENTER(ip, rp, slot) do { \u005c\n \t\tconst unsigned char *t0_newip; \u005c\n@@ -848,7 +847,7 @@ name(void *ctx) \u005c\n \tT0_ENTER(t0ctx-\u003eip, t0ctx-\u003erp, slot); \u005c\n }\n \n-T0_DEFENTRY(br_x509_minimal_init_main, 138)\n+T0_DEFENTRY(br_x509_minimal_init_main, 136)\n \n void\n br_x509_minimal_run(void *t0ctx)\n@@ -1100,7 +1099,7 @@ br_x509_minimal_run(void *t0ctx)\n \t\tif (ta-\u003eflags \u0026 BR_X509_TA_CA) {\n \t\t\tcontinue;\n \t\t}\n-\t\thash_dn(CTX, ta-\u003edn, ta-\u003edn_len, hashed_DN);\n+\t\thash_dn(CTX, ta-\u003edn.data, ta-\u003edn.len, hashed_DN);\n \t\tif (memcmp(hashed_DN, CTX-\u003ecurrent_dn_hash, DNHASH_LEN)) {\n \t\t\tcontinue;\n \t\t}\n@@ -1161,7 +1160,7 @@ br_x509_minimal_run(void *t0ctx)\n \t\tif (!(ta-\u003eflags \u0026 BR_X509_TA_CA)) {\n \t\t\tcontinue;\n \t\t}\n-\t\thash_dn(CTX, ta-\u003edn, ta-\u003edn_len, hashed_DN);\n+\t\thash_dn(CTX, ta-\u003edn.data, ta-\u003edn.len, hashed_DN);\n \t\tif (memcmp(hashed_DN, CTX-\u003esaved_dn_hash, DNHASH_LEN)) {\n \t\t\tcontinue;\n \t\t}\n@@ -1360,14 +1359,6 @@ br_x509_minimal_run(void *t0ctx)\n \t\t\t\t}\n \t\t\t\tbreak;\n \t\t\tcase 42: {\n-\t\t\t\t/* get8 */\n-\n-\tuint32_t addr \u003d T0_POP();\n-\tT0_PUSH(*((unsigned char *)CTX + addr));\n-\n-\t\t\t\t}\n-\t\t\t\tbreak;\n-\t\t\tcase 43: {\n \t\t\t\t/* match-server-name */\n \n \tsize_t n1, n2;\n@@ -1402,7 +1393,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 44: {\n+\t\t\tcase 43: {\n \t\t\t\t/* neg */\n \n \tuint32_t a \u003d T0_POP();\n@@ -1410,7 +1401,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 45: {\n+\t\t\tcase 44: {\n \t\t\t\t/* or */\n \n \tuint32_t b \u003d T0_POP();\n@@ -1419,12 +1410,12 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 46: {\n+\t\t\tcase 45: {\n \t\t\t\t/* over */\n T0_PUSH(T0_PEEK(1)); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 47: {\n+\t\t\tcase 46: {\n \t\t\t\t/* read-blob-inner */\n \n \tuint32_t len \u003d T0_POP();\n@@ -1450,7 +1441,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 48: {\n+\t\t\tcase 47: {\n \t\t\t\t/* read8-low */\n \n \tif (CTX-\u003ehlen \u003d\u003d 0) {\n@@ -1469,17 +1460,17 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 49: {\n+\t\t\tcase 48: {\n \t\t\t\t/* roll */\n T0_ROLL(T0_POP()); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 50: {\n+\t\t\tcase 49: {\n \t\t\t\t/* rot */\n T0_ROT(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 51: {\n+\t\t\tcase 50: {\n \t\t\t\t/* set16 */\n \n \tuint32_t addr \u003d T0_POP();\n@@ -1487,7 +1478,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 52: {\n+\t\t\tcase 51: {\n \t\t\t\t/* set32 */\n \n \tuint32_t addr \u003d T0_POP();\n@@ -1495,7 +1486,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 53: {\n+\t\t\tcase 52: {\n \t\t\t\t/* set8 */\n \n \tuint32_t addr \u003d T0_POP();\n@@ -1503,7 +1494,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 54: {\n+\t\t\tcase 53: {\n \t\t\t\t/* start-dn-hash */\n \n \tCTX-\u003edn_hash_impl-\u003einit(\u0026CTX-\u003edn_hash.vtable);\n@@ -1511,7 +1502,7 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 55: {\n+\t\t\tcase 54: {\n \t\t\t\t/* start-tbs-hash */\n \n \tbr_multihash_init(\u0026CTX-\u003emhash);\n@@ -1519,19 +1510,19 @@ br_x509_minimal_run(void *t0ctx)\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 56: {\n+\t\t\tcase 55: {\n \t\t\t\t/* stop-tbs-hash */\n \n \tCTX-\u003edo_mhash \u003d 0;\n \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 57: {\n+\t\t\tcase 56: {\n \t\t\t\t/* swap */\n T0_SWAP(); \n \t\t\t\t}\n \t\t\t\tbreak;\n-\t\t\tcase 58: {\n+\t\t\tcase 57: {\n \t\t\t\t/* zero-server-name */\n \n \tT0_PUSHi(-(CTX-\u003eserver_name \u003d\u003d NULL));\ndiff --git a/src/x509/x509_minimal.t0 b/src/x509/x509_minimal.t0\nindex bdb3e18..385972b 100644\n--- a/src/x509/x509_minimal.t0\n+++ b/src/x509/x509_minimal.t0\n@@ -188,8 +188,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,\n }\n \n static void\n-xm_start_chain(const br_x509_class **ctx,\n-\tunsigned expected_key_type, const char *server_name)\n+xm_start_chain(const br_x509_class **ctx, const char *server_name)\n {\n \tbr_x509_minimal_context *cc;\n \n@@ -200,7 +199,6 @@ xm_start_chain(const br_x509_class **ctx,\n \tcc-\u003ecpu.dp \u003d cc-\u003edp_stack;\n \tcc-\u003ecpu.rp \u003d cc-\u003erp_stack;\n \tbr_x509_minimal_init_main(\u0026cc-\u003ecpu);\n-\tcc-\u003eexpected_key_type \u003d expected_key_type;\n \tif (server_name \u003d\u003d NULL || *server_name \u003d\u003d 0) {\n \t\tcc-\u003eserver_name \u003d NULL;\n \t} else {\n@@ -269,7 +267,7 @@ xm_end_chain(const br_x509_class **ctx)\n }\n \n static const br_x509_pkey *\n-xm_get_pkey(const br_x509_class *const *ctx)\n+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)\n {\n \tbr_x509_minimal_context *cc;\n \n@@ -277,6 +275,9 @@ xm_get_pkey(const br_x509_class *const *ctx)\n \tif (cc-\u003eerr \u003d\u003d BR_ERR_X509_OK\n \t\t|| cc-\u003eerr \u003d\u003d BR_ERR_X509_NOT_TRUSTED)\n \t{\n+\t\tif (usages !\u003d NULL) {\n+\t\t\t*usages \u003d cc-\u003ekey_usages;\n+\t\t}\n \t\treturn \u0026((br_x509_minimal_context *)ctx)-\u003epkey;\n \t} else {\n \t\treturn NULL;\n@@ -472,7 +473,7 @@ cc: zero-server-name ( -- bool ) {\n \tT0_PUSHi(-(CTX-\u003eserver_name \u003d\u003d NULL));\n }\n \n-addr: expected_key_type\n+addr: key_usages\n addr: cert_sig\n addr: cert_sig_len\n addr: cert_signer_key_type\n@@ -705,7 +706,7 @@ cc: check-direct-trust ( -- ) {\n \t\tif (ta-\u003eflags \u0026 BR_X509_TA_CA) {\n \t\t\tcontinue;\n \t\t}\n-\t\thash_dn(CTX, ta-\u003edn, ta-\u003edn_len, hashed_DN);\n+\t\thash_dn(CTX, ta-\u003edn.data, ta-\u003edn.len, hashed_DN);\n \t\tif (memcmp(hashed_DN, CTX-\u003ecurrent_dn_hash, DNHASH_LEN)) {\n \t\t\tcontinue;\n \t\t}\n@@ -765,7 +766,7 @@ cc: check-trust-anchor-CA ( -- ) {\n \t\tif (!(ta-\u003eflags \u0026 BR_X509_TA_CA)) {\n \t\t\tcontinue;\n \t\t}\n-\t\thash_dn(CTX, ta-\u003edn, ta-\u003edn_len, hashed_DN);\n+\t\thash_dn(CTX, ta-\u003edn.data, ta-\u003edn.len, hashed_DN);\n \t\tif (memcmp(hashed_DN, CTX-\u003esaved_dn_hash, DNHASH_LEN)) {\n \t\t\tcontinue;\n \t\t}\n@@ -892,20 +893,14 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11\n \n \u005c Process a Key Usage extension.\n \u005c For the EE certificate:\n-\u005c -- if the expected key usage is \u0022key exchange\u0022, then the extension\n-\u005c must contain either keyEncipherment (2) or dataEncipherment (3);\n-\u005c -- if the expected key usage is \u0022signature\u0022, then the extension\n-\u005c must contain either digitalSignature (0) or nonRepudiation (1).\n+\u005c -- if the key usage contains keyEncipherment (2), dataEncipherment (3)\n+\u005c or keyAgreement (4), then the \u0022key exchange\u0022 usage is allowed;\n+\u005c -- if the key usage contains digitalSignature (0) or nonRepudiation (1),\n+\u005c then the \u0022signature\u0022 usage is allowed.\n \u005c For CA certificates, the extension must contain keyCertSign (5).\n : process-keyUsage ( lim ee -- lim )\n-\t\u005c Compute flags, depending on EE status and expected key usage.\n-\t\u005c This is a mask of bits in the first byte.\n-\tif\n-\t\taddr-expected_key_type get8 0x10 and if 0x30 else 0xC0 then\n-\telse\n-\t\t0x04\n-\tthen\n-\t{ mask }\n+\t{ ee }\n+\n \t\u005c Read tag for the BIT STRING and open it.\n \tread-tag 0x03 check-tag-primitive\n \tread-length-open-elt\n@@ -919,7 +914,20 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11\n \t\t1 of read8 ign \u003e\u003e ign \u003c\u003c endof\n \t\tdrop read8 0\n \tendcase\n-\tmask and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then\n+\n+\t\u005c Check bits.\n+\tee if\n+\t\t\u005c EE: get usages.\n+\t\t0\n+\t\tover 0x38 and if 0x10 or then\n+\t\tswap 0xC0 and if 0x20 or then\n+\t\taddr-key_usages set8\n+\telse\n+\t\t\u005c Not EE: keyCertSign must be set.\n+\t\t0x04 and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then\n+\tthen\n+\n+\t\u005c We don't care about subsequent bytes.\n \tskip-close-elt ;\n \n \u005c Process a Subject Alt Name extension. Returned value is a boolean set\n@@ -1070,15 +1078,8 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11\n \n \t\u005c Process public key.\n \tee if\n-\t\t\u005c For the EE certificate, check that the key type\n-\t\t\u005c matches that which was expected, then copy the\n-\t\t\u005c data to the relevant buffer.\n-\t\taddr-expected_key_type get8 0x0F and\n-\t\tdup if\n-\t\t\tpkey-type \u003d ifnot ERR_X509_WRONG_KEY_TYPE fail then\n-\t\telse\n-\t\t\tdrop\n-\t\tthen\n+\t\t\u005c For the EE certificate, copy the key data to the\n+\t\t\u005c relevant buffer.\n \t\tpkey-type case\n \t\t\tKEYTYPE_RSA of nlen elen copy-ee-rsa-pkey endof\n \t\t\tKEYTYPE_EC of curve qlen copy-ee-ec-pkey endof\n@@ -1286,6 +1287,9 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11\n \tcheck-trust-anchor-CA ;\n \n : main\n+\t\u005c Unless restricted by a Key Usage extension, all usages are\n+\t\u005c deemed allowed.\n+\t0x30 addr-key_usages set8\n \t-1 decode-certificate\n \tco\n \tbegin\ndiff --git a/test/test_x509.c b/test/test_x509.c\nindex 52a9e2c..c4f0885 100644\n--- a/test/test_x509.c\n+++ b/test/test_x509.c\n@@ -1438,6 +1438,7 @@ run_test_case(test_case *tc)\n \tblob *certs;\n \tbr_x509_pkey *ee_pkey_ref;\n \tconst br_x509_pkey *ee_pkey;\n+\tunsigned usages;\n \tunsigned status;\n \n \tprintf(\u0022%s: \u0022, tc-\u003ename);\n@@ -1477,8 +1478,8 @@ run_test_case(test_case *tc)\n \t\t\t\ttta-\u003ekey_name);\n \t\t\texit(EXIT_FAILURE);\n \t\t}\n-\t\tanchors[u].dn \u003d tta-\u003edn;\n-\t\tanchors[u].dn_len \u003d tta-\u003edn_len;\n+\t\tanchors[u].dn.data \u003d tta-\u003edn;\n+\t\tanchors[u].dn.len \u003d tta-\u003edn_len;\n \t\tanchors[u].flags \u003d tta-\u003eflags;\n \t\tanchors[u].pkey \u003d *tak;\n \t}\n@@ -1541,8 +1542,7 @@ run_test_case(test_case *tc)\n \t * Run the engine. We inject certificates by chunks of 100 bytes\n \t * in order to exercise the coroutine API.\n \t */\n-\tctx.vtable-\u003estart_chain(\u0026ctx.vtable,\n-\t\ttc-\u003ekey_type_usage, tc-\u003eservername);\n+\tctx.vtable-\u003estart_chain(\u0026ctx.vtable, tc-\u003eservername);\n \tfor (u \u003d 0; u \u003c num_certs; u ++) {\n \t\tsize_t v;\n \n@@ -1561,7 +1561,22 @@ run_test_case(test_case *tc)\n \t\tctx.vtable-\u003eend_cert(\u0026ctx.vtable);\n \t}\n \tstatus \u003d ctx.vtable-\u003eend_chain(\u0026ctx.vtable);\n-\tee_pkey \u003d ctx.vtable-\u003eget_pkey(\u0026ctx.vtable);\n+\tee_pkey \u003d ctx.vtable-\u003eget_pkey(\u0026ctx.vtable, \u0026usages);\n+\n+\t/*\n+\t * Check key type and usage.\n+\t */\n+\tif (ee_pkey !\u003d NULL) {\n+\t\tunsigned ktu;\n+\n+\t\tktu \u003d ee_pkey-\u003ekey_type | usages;\n+\t\tif (tc-\u003ekey_type_usage !\u003d (ktu \u0026 tc-\u003ekey_type_usage)) {\n+\t\t\tfprintf(stderr, \u0022wrong key type + usage\u0022\n+\t\t\t\t\u0022 (expected 0x%02X, got 0x%02X)\u005cn\u0022,\n+\t\t\t\ttc-\u003ekey_type_usage, ktu);\n+\t\t\texit(EXIT_FAILURE);\n+\t\t}\n+\t}\n \n \t/*\n \t * Check results. Note that we may still get a public key if\ndiff --git a/tools/brssl.h b/tools/brssl.h\nindex a3ceb14..e93ed4c 100644\n--- a/tools/brssl.h\n+++ b/tools/brssl.h\n@@ -280,6 +280,11 @@ void list_names(void);\n const char *ec_curve_name(int curve);\n \n /*\n+ * Get the symbolic name for a hash function name (by ID).\n+ */\n+const char *hash_function_name(int id);\n+\n+/*\n * Read a file completely. The returned block is allocated with xmalloc()\n * and must be released by the caller.\n * If the file cannot be found or read completely, or is empty, then an\n@@ -343,6 +348,12 @@ pem_object *decode_pem(const void *src, size_t len, size_t *num);\n br_x509_certificate *read_certificates(const char *fname, size_t *num);\n \n /*\n+ * Release certificates. This releases all certificate data arrays,\n+ * and the whole array as well.\n+ */\n+void free_certificates(br_x509_certificate *certs, size_t num);\n+\n+/*\n * Interpret a certificate as a trust anchor. The trust anchor is\n * newly allocated with xmalloc() and the caller must release it.\n * On decoding error, an error message is printed, and this function\n@@ -370,6 +381,12 @@ void free_ta_contents(br_x509_trust_anchor *ta);\n size_t read_trust_anchors(anchor_list *dst, const char *fname);\n \n /*\n+ * Get the \u0022signer key type\u0022 for the certificate (key type of the\n+ * issuing CA). On error, this prints a message on stderr, and returns 0.\n+ */\n+int get_cert_signer_algo(br_x509_certificate *xc);\n+\n+/*\n * Special \u0022no anchor\u0022 X.509 validator that wraps around another X.509\n * validator and turns \u0022not trusted\u0022 error codes into success. This is\n * by definition insecure, but convenient for debug purposes.\n@@ -409,6 +426,20 @@ private_key *read_private_key(const char *fname);\n void free_private_key(private_key *sk);\n \n /*\n+ * Get the encoded OID for a given hash function (to use with PKCS#1\n+ * signatures). If the hash function ID is 0 (for MD5+SHA-1), or if\n+ * the ID is not one of the SHA-* functions (SHA-1, SHA-224, SHA-256,\n+ * SHA-384, SHA-512), then this function returns NULL.\n+ */\n+const unsigned char *get_hash_oid(int id);\n+\n+/*\n+ * Get a hash implementation by ID. This returns NULL if the hash\n+ * implementation is not available.\n+ */\n+const br_hash_class *get_hash_impl(int id);\n+\n+/*\n * Find the symbolic name and the description for an error. If 'err' is\n * recognised then the error symbolic name is returned; if 'comment' is\n * not NULL then '*comment' is then set to a descriptive human-readable\ndiff --git a/tools/certs.c b/tools/certs.c\nindex fdee5c6..91ca9b9 100644\n--- a/tools/certs.c\n+++ b/tools/certs.c\n@@ -53,8 +53,8 @@ certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,\n \t\tVEC_CLEAR(vdn);\n \t\treturn -1;\n \t}\n-\tta-\u003edn \u003d VEC_TOARRAY(vdn);\n-\tta-\u003edn_len \u003d VEC_LEN(vdn);\n+\tta-\u003edn.data \u003d VEC_TOARRAY(vdn);\n+\tta-\u003edn.len \u003d VEC_LEN(vdn);\n \tVEC_CLEAR(vdn);\n \tta-\u003eflags \u003d 0;\n \tif (br_x509_decoder_isCA(\u0026dc)) {\n@@ -76,7 +76,7 @@ certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,\n \t\tbreak;\n \tdefault:\n \t\tfprintf(stderr, \u0022ERROR: unsupported public key type in CA\u005cn\u0022);\n-\t\txfree(ta-\u003edn);\n+\t\txfree(ta-\u003edn.data);\n \t\treturn -1;\n \t}\n \treturn 0;\n@@ -99,7 +99,7 @@ certificate_to_trust_anchor(br_x509_certificate *xc)\n void\n free_ta_contents(br_x509_trust_anchor *ta)\n {\n-\txfree(ta-\u003edn);\n+\txfree(ta-\u003edn.data);\n \tswitch (ta-\u003epkey.key_type) {\n \tcase BR_KEYTYPE_RSA:\n \t\txfree(ta-\u003epkey.key.rsa.n);\n@@ -137,15 +137,32 @@ read_trust_anchors(anchor_list *dst, const char *fname)\n \treturn num;\n }\n \n+/* see brssl.h */\n+int\n+get_cert_signer_algo(br_x509_certificate *xc)\n+{\n+\tbr_x509_decoder_context dc;\n+\tint err;\n+\n+\tbr_x509_decoder_init(\u0026dc, 0, 0);\n+\tbr_x509_decoder_push(\u0026dc, xc-\u003edata, xc-\u003edata_len);\n+\terr \u003d br_x509_decoder_last_error(\u0026dc);\n+\tif (err !\u003d 0) {\n+\t\tfprintf(stderr,\n+\t\t\t\u0022ERROR: certificate decoding failed with error %d\u005cn\u0022,\n+\t\t\t-err);\n+\t\treturn 0;\n+\t}\n+\treturn br_x509_decoder_get_signer_key_type(\u0026dc);\n+}\n+\n static void\n-xwc_start_chain(const br_x509_class **ctx,\n-\tunsigned expected_key_type, const char *server_name)\n+xwc_start_chain(const br_x509_class **ctx, const char *server_name)\n {\n \tx509_noanchor_context *xwc;\n \n \txwc \u003d (x509_noanchor_context *)ctx;\n-\t(*xwc-\u003einner)-\u003estart_chain(xwc-\u003einner,\n-\t\texpected_key_type, server_name);\n+\t(*xwc-\u003einner)-\u003estart_chain(xwc-\u003einner, server_name);\n }\n \n static void\n@@ -190,12 +207,12 @@ xwc_end_chain(const br_x509_class **ctx)\n }\n \n static const br_x509_pkey *\n-xwc_get_pkey(const br_x509_class *const *ctx)\n+xwc_get_pkey(const br_x509_class *const *ctx, unsigned *usages)\n {\n \tx509_noanchor_context *xwc;\n \n \txwc \u003d (x509_noanchor_context *)ctx;\n-\treturn (*xwc-\u003einner)-\u003eget_pkey(xwc-\u003einner);\n+\treturn (*xwc-\u003einner)-\u003eget_pkey(xwc-\u003einner, usages);\n }\n \n /* see brssl.h */\ndiff --git a/tools/client.c b/tools/client.c\nindex 72bdbd1..102d43b 100644\n--- a/tools/client.c\n+++ b/tools/client.c\n@@ -117,6 +117,308 @@ host_connect(const char *host, const char *port, int verbose)\n \treturn fd;\n }\n \n+typedef struct {\n+\tconst br_ssl_client_certificate_class *vtable;\n+\tint verbose;\n+\tbr_x509_certificate *chain;\n+\tsize_t chain_len;\n+\tprivate_key *sk;\n+\tint issuer_key_type;\n+} ccert_context;\n+\n+static void\n+cc_start_name_list(const br_ssl_client_certificate_class **pctx)\n+{\n+\tccert_context *zc;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tif (zc-\u003everbose) {\n+\t\tfprintf(stderr, \u0022Server requests a client certificate.\u005cn\u0022);\n+\t\tfprintf(stderr, \u0022--- anchor DN list start ---\u005cn\u0022);\n+\t}\n+}\n+\n+static void\n+cc_start_name(const br_ssl_client_certificate_class **pctx, size_t len)\n+{\n+\tccert_context *zc;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tif (zc-\u003everbose) {\n+\t\tfprintf(stderr, \u0022new anchor name, length \u003d %u\u005cn\u0022,\n+\t\t\t(unsigned)len);\n+\t}\n+}\n+\n+static void\n+cc_append_name(const br_ssl_client_certificate_class **pctx,\n+\tconst unsigned char *data, size_t len)\n+{\n+\tccert_context *zc;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tif (zc-\u003everbose) {\n+\t\tsize_t u;\n+\n+\t\tfor (u \u003d 0; u \u003c len; u ++) {\n+\t\t\tif (u \u003d\u003d 0) {\n+\t\t\t\tfprintf(stderr, \u0022 \u0022);\n+\t\t\t} else if (u \u003e 0 \u0026\u0026 u % 16 \u003d\u003d 0) {\n+\t\t\t\tfprintf(stderr, \u0022\u005cn \u0022);\n+\t\t\t}\n+\t\t\tfprintf(stderr, \u0022 %02x\u0022, data[u]);\n+\t\t}\n+\t\tif (len \u003e 0) {\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n+\t\t}\n+\t}\n+}\n+\n+static void\n+cc_end_name(const br_ssl_client_certificate_class **pctx)\n+{\n+\t(void)pctx;\n+}\n+\n+static void\n+cc_end_name_list(const br_ssl_client_certificate_class **pctx)\n+{\n+\tccert_context *zc;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tif (zc-\u003everbose) {\n+\t\tfprintf(stderr, \u0022--- anchor DN list end ---\u005cn\u0022);\n+\t}\n+}\n+\n+static void\n+print_hashes(unsigned hh, unsigned hh2)\n+{\n+\tint i;\n+\n+\tfor (i \u003d 0; i \u003c 8; i ++) {\n+\t\tconst char *name;\n+\n+\t\tname \u003d hash_function_name(i);\n+\t\tif (((hh \u003e\u003e i) \u0026 1) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022 %s\u0022, name);\n+\t\t} else if (((hh2 \u003e\u003e i) \u0026 1) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022 (%s)\u0022, name);\n+\t\t}\n+\t}\n+}\n+\n+static int\n+choose_hash(unsigned hh)\n+{\n+\tstatic const int f[] \u003d {\n+\t\tbr_sha256_ID, br_sha224_ID, br_sha384_ID, br_sha512_ID,\n+\t\tbr_sha1_ID, br_md5sha1_ID, -1\n+\t};\n+\n+\tsize_t u;\n+\n+\tfor (u \u003d 0; f[u] \u003e\u003d 0; u ++) {\n+\t\tif (((hh \u003e\u003e f[u]) \u0026 1) !\u003d 0) {\n+\t\t\treturn f[u];\n+\t\t}\n+\t}\n+\treturn -1;\n+}\n+\n+static void\n+cc_choose(const br_ssl_client_certificate_class **pctx,\n+\tconst br_ssl_client_context *cc, uint32_t auth_types,\n+\tbr_ssl_client_certificate *choices)\n+{\n+\tccert_context *zc;\n+\tint scurve;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tscurve \u003d br_ssl_client_get_server_curve(cc);\n+\tif (zc-\u003everbose) {\n+\t\tunsigned hashes;\n+\n+\t\thashes \u003d br_ssl_client_get_server_hashes(cc);\n+\t\tif ((auth_types \u0026 0x00FF) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022supported: RSA signatures:\u0022);\n+\t\t\tprint_hashes(auth_types, hashes);\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n+\t\t}\n+\t\tif ((auth_types \u0026 0xFF00) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022supported: ECDSA signatures:\u0022);\n+\t\t\tprint_hashes(auth_types \u003e\u003e 8, hashes \u003e\u003e 8);\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n+\t\t}\n+\t\tif ((auth_types \u0026 0x010000) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022supported:\u0022\n+\t\t\t\t\u0022 fixed ECDH (cert signed with RSA)\u005cn\u0022);\n+\t\t}\n+\t\tif ((auth_types \u0026 0x020000) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022supported:\u0022\n+\t\t\t\t\u0022 fixed ECDH (cert signed with ECDSA)\u005cn\u0022);\n+\t\t}\n+\t\tif (scurve) {\n+\t\t\tfprintf(stderr, \u0022server key curve: %s (%d)\u005cn\u0022,\n+\t\t\t\tec_curve_name(scurve), scurve);\n+\t\t} else {\n+\t\t\tfprintf(stderr, \u0022server key is not EC\u005cn\u0022);\n+\t\t}\n+\t}\n+\tswitch (zc-\u003esk-\u003ekey_type) {\n+\tcase BR_KEYTYPE_RSA:\n+\t\tif ((choices-\u003ehash_id \u003d choose_hash(auth_types)) \u003e\u003d 0) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022using RSA, hash \u003d %d (%s)\u005cn\u0022,\n+\t\t\t\t\tchoices-\u003ehash_id,\n+\t\t\t\t\thash_function_name(choices-\u003ehash_id));\n+\t\t\t}\n+\t\t\tchoices-\u003eauth_type \u003d BR_AUTH_RSA;\n+\t\t\tchoices-\u003echain \u003d zc-\u003echain;\n+\t\t\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+\t\t\treturn;\n+\t\t}\n+\t\tbreak;\n+\tcase BR_KEYTYPE_EC:\n+\t\tif (zc-\u003eissuer_key_type !\u003d 0\n+\t\t\t\u0026\u0026 scurve \u003d\u003d zc-\u003esk-\u003ekey.ec.curve)\n+\t\t{\n+\t\t\tint x;\n+\n+\t\t\tx \u003d (zc-\u003eissuer_key_type \u003d\u003d BR_KEYTYPE_RSA) ? 16 : 17;\n+\t\t\tif (((auth_types \u003e\u003e x) \u0026 1) !\u003d 0) {\n+\t\t\t\tif (zc-\u003everbose) {\n+\t\t\t\t\tfprintf(stderr, \u0022using static ECDH\u005cn\u0022);\n+\t\t\t\t}\n+\t\t\t\tchoices-\u003eauth_type \u003d BR_AUTH_ECDH;\n+\t\t\t\tchoices-\u003ehash_id \u003d -1;\n+\t\t\t\tchoices-\u003echain \u003d zc-\u003echain;\n+\t\t\t\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n+\t\tif ((choices-\u003ehash_id \u003d choose_hash(auth_types \u003e\u003e 8)) \u003e\u003d 0) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022using ECDSA, hash \u003d %d (%s)\u005cn\u0022,\n+\t\t\t\t\tchoices-\u003ehash_id,\n+\t\t\t\t\thash_function_name(choices-\u003ehash_id));\n+\t\t\t}\n+\t\t\tchoices-\u003eauth_type \u003d BR_AUTH_ECDSA;\n+\t\t\tchoices-\u003echain \u003d zc-\u003echain;\n+\t\t\tchoices-\u003echain_len \u003d zc-\u003echain_len;\n+\t\t\treturn;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\tif (zc-\u003everbose) {\n+\t\tfprintf(stderr, \u0022no matching client certificate\u005cn\u0022);\n+\t}\n+\tchoices-\u003echain \u003d NULL;\n+\tchoices-\u003echain_len \u003d 0;\n+}\n+\n+static uint32_t\n+cc_do_keyx(const br_ssl_client_certificate_class **pctx,\n+\tunsigned char *data, size_t len)\n+{\n+\tccert_context *zc;\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\treturn br_ec_prime_i31.mul(data, len, zc-\u003esk-\u003ekey.ec.x,\n+\t\tzc-\u003esk-\u003ekey.ec.xlen, zc-\u003esk-\u003ekey.ec.curve);\n+}\n+\n+static size_t\n+cc_do_sign(const br_ssl_client_certificate_class **pctx,\n+\tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n+{\n+\tccert_context *zc;\n+\tunsigned char hv[64];\n+\n+\tzc \u003d (ccert_context *)pctx;\n+\tmemcpy(hv, data, hv_len);\n+\tswitch (zc-\u003esk-\u003ekey_type) {\n+\t\tconst br_hash_class *hc;\n+\t\tconst unsigned char *hash_oid;\n+\t\tuint32_t x;\n+\t\tsize_t sig_len;\n+\n+\tcase BR_KEYTYPE_RSA:\n+\t\thash_oid \u003d get_hash_oid(hash_id);\n+\t\tif (hash_oid \u003d\u003d NULL \u0026\u0026 hash_id !\u003d 0) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: cannot RSA-sign with\u0022\n+\t\t\t\t\t\u0022 unknown hash function: %d\u005cn\u0022,\n+\t\t\t\t\thash_id);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\tsig_len \u003d (zc-\u003esk-\u003ekey.rsa.n_bitlen + 7) \u003e\u003e 3;\n+\t\tif (len \u003c sig_len) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: cannot RSA-sign,\u0022\n+\t\t\t\t\t\u0022 buffer is too small\u0022\n+\t\t\t\t\t\u0022 (sig\u003d%lu, buf\u003d%lu)\u005cn\u0022,\n+\t\t\t\t\t(unsigned long)sig_len,\n+\t\t\t\t\t(unsigned long)len);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\tx \u003d br_rsa_i31_pkcs1_sign(hash_oid, hv, hv_len,\n+\t\t\t\u0026zc-\u003esk-\u003ekey.rsa, data);\n+\t\tif (!x) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: RSA-sign failure\u005cn\u0022);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\treturn sig_len;\n+\n+\tcase BR_KEYTYPE_EC:\n+\t\thc \u003d get_hash_impl(hash_id);\n+\t\tif (hc \u003d\u003d NULL) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: cannot ECDSA-sign with\u0022\n+\t\t\t\t\t\u0022 unknown hash function: %d\u005cn\u0022,\n+\t\t\t\t\thash_id);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\tif (len \u003c 139) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: cannot ECDSA-sign\u0022\n+\t\t\t\t\t\u0022 (output buffer \u003d %lu)\u005cn\u0022,\n+\t\t\t\t\t(unsigned long)len);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\tsig_len \u003d br_ecdsa_i31_sign_asn1(\u0026br_ec_prime_i31,\n+\t\t\thc, hv, \u0026zc-\u003esk-\u003ekey.ec, data);\n+\t\tif (sig_len \u003d\u003d 0) {\n+\t\t\tif (zc-\u003everbose) {\n+\t\t\t\tfprintf(stderr, \u0022ERROR: ECDSA-sign failure\u005cn\u0022);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\treturn sig_len;\n+\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+}\n+\n+static const br_ssl_client_certificate_class ccert_vtable \u003d {\n+\tsizeof(ccert_context),\n+\tcc_start_name_list,\n+\tcc_start_name,\n+\tcc_append_name,\n+\tcc_end_name,\n+\tcc_end_name_list,\n+\tcc_choose,\n+\tcc_do_keyx,\n+\tcc_do_sign\n+};\n+\n static void\n usage_client(void)\n {\n@@ -139,6 +441,12 @@ usage_client(void)\n \tfprintf(stderr,\n \u0022 -CA file add certificates in 'file' to trust anchors\u005cn\u0022);\n \tfprintf(stderr,\n+\u0022 -cert file set client certificate chain\u005cn\u0022);\n+\tfprintf(stderr,\n+\u0022 -key file set client private key (for certificate authentication)\u005cn\u0022);\n+\tfprintf(stderr,\n+\u0022 -nostaticecdh prohibit full-static ECDH (client certificate)\u005cn\u0022);\n+\tfprintf(stderr,\n \u0022 -list list supported names (protocols, algorithms...)\u005cn\u0022);\n \tfprintf(stderr,\n \u0022 -vmin name set minimum supported version (default: TLS-1.0)\u005cn\u0022);\n@@ -179,6 +487,11 @@ do_client(int argc, char *argv[])\n \tbr_x509_minimal_context xc;\n \tx509_noanchor_context xwc;\n \tconst br_hash_class *dnhash;\n+\tccert_context zc;\n+\tbr_x509_certificate *chain;\n+\tsize_t chain_len;\n+\tprivate_key *sk;\n+\tint nostaticecdh;\n \tunsigned char *iobuf;\n \tsize_t iobuf_len;\n \tsize_t minhello_len;\n@@ -200,6 +513,10 @@ do_client(int argc, char *argv[])\n \tnum_suites \u003d 0;\n \thfuns \u003d 0;\n \tsuite_ids \u003d NULL;\n+\tchain \u003d NULL;\n+\tchain_len \u003d 0;\n+\tsk \u003d NULL;\n+\tnostaticecdh \u003d 0;\n \tiobuf \u003d NULL;\n \tiobuf_len \u003d 0;\n \tminhello_len \u003d (size_t)-1;\n@@ -279,6 +596,44 @@ do_client(int argc, char *argv[])\n \t\t\t\tusage_client();\n \t\t\t\tgoto client_exit_error;\n \t\t\t}\n+\t\t} else if (eqstr(arg, \u0022-cert\u0022)) {\n+\t\t\tif (++ i \u003e\u003d argc) {\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\u0022ERROR: no argument for '-cert'\u005cn\u0022);\n+\t\t\t\tusage_client();\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t\tif (chain !\u003d NULL) {\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\u0022ERROR: duplicate certificate chain\u005cn\u0022);\n+\t\t\t\tusage_client();\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t\targ \u003d argv[i];\n+\t\t\tchain \u003d read_certificates(arg, \u0026chain_len);\n+\t\t\tif (chain \u003d\u003d NULL || chain_len \u003d\u003d 0) {\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t} else if (eqstr(arg, \u0022-key\u0022)) {\n+\t\t\tif (++ i \u003e\u003d argc) {\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\u0022ERROR: no argument for '-key'\u005cn\u0022);\n+\t\t\t\tusage_client();\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t\tif (sk !\u003d NULL) {\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\u0022ERROR: duplicate private key\u005cn\u0022);\n+\t\t\t\tusage_client();\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t\targ \u003d argv[i];\n+\t\t\tsk \u003d read_private_key(arg);\n+\t\t\tif (sk \u003d\u003d NULL) {\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t} else if (eqstr(arg, \u0022-nostaticecdh\u0022)) {\n+\t\t\tnostaticecdh \u003d 1;\n \t\t} else if (eqstr(arg, \u0022-list\u0022)) {\n \t\t\tlist_names();\n \t\t\tgoto client_exit;\n@@ -412,7 +767,7 @@ do_client(int argc, char *argv[])\n \t}\n \tif (u \u003d\u003d 0) {\n \t\thost \u003d xstrdup(server_name);\n-\t\tport \u003d \u0022443\u0022;\n+\t\tport \u003d xstrdup(\u0022443\u0022);\n \t} else {\n \t\tport \u003d xstrdup(server_name + u);\n \t\thost \u003d xmalloc(u);\n@@ -423,6 +778,19 @@ do_client(int argc, char *argv[])\n \t\tsni \u003d host;\n \t}\n \n+\tif (chain \u003d\u003d NULL \u0026\u0026 sk !\u003d NULL) {\n+\t\tfprintf(stderr, \u0022ERROR: private key specified, but\u0022\n+\t\t\t\u0022 no certificate chain\u005cn\u0022);\n+\t\tusage_client();\n+\t\tgoto client_exit_error;\n+\t}\n+\tif (chain !\u003d NULL \u0026\u0026 sk \u003d\u003d NULL) {\n+\t\tfprintf(stderr, \u0022ERROR: certificate chain specified, but\u0022\n+\t\t\t\u0022 no private key\u005cn\u0022);\n+\t\tusage_client();\n+\t\tgoto client_exit_error;\n+\t}\n+\n \tif (vmin \u003d\u003d 0) {\n \t\tvmin \u003d BR_TLS10;\n \t}\n@@ -560,11 +928,13 @@ do_client(int argc, char *argv[])\n \t\t}\n \t\tif ((req \u0026 REQ_ECDHE_RSA) !\u003d 0) {\n \t\t\tbr_ssl_engine_set_ec(\u0026cc.eng, \u0026br_ec_prime_i31);\n-\t\t\tbr_ssl_client_set_rsavrfy(\u0026cc, \u0026br_rsa_i31_pkcs1_vrfy);\n+\t\t\tbr_ssl_engine_set_rsavrfy(\u0026cc.eng,\n+\t\t\t\t\u0026br_rsa_i31_pkcs1_vrfy);\n \t\t}\n \t\tif ((req \u0026 REQ_ECDHE_ECDSA) !\u003d 0) {\n \t\t\tbr_ssl_engine_set_ec(\u0026cc.eng, \u0026br_ec_prime_i31);\n-\t\t\tbr_ssl_client_set_ecdsa(\u0026cc, \u0026br_ecdsa_i31_vrfy_asn1);\n+\t\t\tbr_ssl_engine_set_ecdsa(\u0026cc.eng,\n+\t\t\t\t\u0026br_ecdsa_i31_vrfy_asn1);\n \t\t}\n \t\tif ((req \u0026 REQ_ECDH) !\u003d 0) {\n \t\t\tbr_ssl_engine_set_ec(\u0026cc.eng, \u0026br_ec_prime_i31);\n@@ -624,6 +994,23 @@ do_client(int argc, char *argv[])\n \t}\n \tbr_ssl_engine_set_all_flags(\u0026cc.eng, flags);\n \n+\tif (chain !\u003d NULL) {\n+\t\tzc.vtable \u003d \u0026ccert_vtable;\n+\t\tzc.verbose \u003d verbose;\n+\t\tzc.chain \u003d chain;\n+\t\tzc.chain_len \u003d chain_len;\n+\t\tzc.sk \u003d sk;\n+\t\tif (nostaticecdh || sk-\u003ekey_type !\u003d BR_KEYTYPE_EC) {\n+\t\t\tzc.issuer_key_type \u003d 0;\n+\t\t} else {\n+\t\t\tzc.issuer_key_type \u003d get_cert_signer_algo(\u0026chain[0]);\n+\t\t\tif (zc.issuer_key_type \u003d\u003d 0) {\n+\t\t\t\tgoto client_exit_error;\n+\t\t\t}\n+\t\t}\n+\t\tbr_ssl_client_set_client_certificate(\u0026cc, \u0026zc.vtable);\n+\t}\n+\n \tbr_ssl_engine_set_buffer(\u0026cc.eng, iobuf, iobuf_len, bidi);\n \tbr_ssl_client_reset(\u0026cc, sni, 0);\n \n@@ -657,9 +1044,12 @@ do_client(int argc, char *argv[])\n \t */\n client_exit:\n \txfree(host);\n+\txfree(port);\n \txfree(suites);\n \txfree(suite_ids);\n \tVEC_CLEAREXT(anchors, \u0026free_ta_contents);\n+\tfree_certificates(chain, chain_len);\n+\tfree_private_key(sk);\n \txfree(iobuf);\n \tif (fd \u003e\u003d 0) {\n \t\tclose(fd);\ndiff --git a/tools/errors.c b/tools/errors.c\nindex e9c6dfa..22f0c30 100644\n--- a/tools/errors.c\n+++ b/tools/errors.c\n@@ -157,7 +157,18 @@ static struct {\n \t}, {\n \t\tBR_ERR_BAD_SIGNATURE,\n \t\t\u0022BR_ERR_BAD_SIGNATURE\u0022,\n-\t\t\u0022Invalid signature on ServerKeyExchange message.\u0022\n+\t\t\u0022Invalid signature in ServerKeyExchange or\u0022\n+\t\t\u0022 CertificateVerify message.\u0022\n+\t}, {\n+\t\tBR_ERR_WRONG_KEY_USAGE,\n+\t\t\u0022BR_ERR_WRONG_KEY_USAGE\u0022,\n+\t\t\u0022Peer's public key does not have the proper type or is\u0022\n+\t\t\u0022 not allowed for the requested operation.\u0022\n+\t}, {\n+\t\tBR_ERR_NO_CLIENT_AUTH,\n+\t\t\u0022BR_ERR_NO_CLIENT_AUTH\u0022,\n+\t\t\u0022Client did not send a certificate upon request, or the\u0022\n+\t\t\u0022 client certificate could not be validated.\u0022\n \t}, {\n \t\tBR_ERR_IO,\n \t\t\u0022BR_ERR_IO\u0022,\ndiff --git a/tools/files.c b/tools/files.c\nindex 21c8166..651d51a 100644\n--- a/tools/files.c\n+++ b/tools/files.c\n@@ -300,3 +300,15 @@ read_certificates(const char *fname, size_t *num)\n \tVEC_CLEAR(cert_list);\n \treturn xcs;\n }\n+\n+/* see brssl.h */\n+void\n+free_certificates(br_x509_certificate *certs, size_t num)\n+{\n+\tsize_t u;\n+\n+\tfor (u \u003d 0; u \u003c num; u ++) {\n+\t\txfree(certs[u].data);\n+\t}\n+\txfree(certs);\n+}\ndiff --git a/tools/keys.c b/tools/keys.c\nindex 278a3b2..f7394be 100644\n--- a/tools/keys.c\n+++ b/tools/keys.c\n@@ -168,3 +168,64 @@ free_private_key(private_key *sk)\n \t}\n \txfree(sk);\n }\n+\n+/*\n+ * OID for hash functions in RSA signatures.\n+ */\n+static const unsigned char HASH_OID_SHA1[] \u003d {\n+\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n+};\n+\n+static const unsigned char HASH_OID_SHA224[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n+};\n+\n+static const unsigned char HASH_OID_SHA256[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n+};\n+\n+static const unsigned char HASH_OID_SHA384[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n+};\n+\n+static const unsigned char HASH_OID_SHA512[] \u003d {\n+\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n+};\n+\n+static const unsigned char *HASH_OID[] \u003d {\n+\tHASH_OID_SHA1,\n+\tHASH_OID_SHA224,\n+\tHASH_OID_SHA256,\n+\tHASH_OID_SHA384,\n+\tHASH_OID_SHA512\n+};\n+\n+/* see brssl.h */\n+const unsigned char *\n+get_hash_oid(int id)\n+{\n+\tif (id \u003e\u003d 2 \u0026\u0026 id \u003c\u003d 6) {\n+\t\treturn HASH_OID[id - 2];\n+\t} else {\n+\t\treturn NULL;\n+\t}\n+}\n+\n+/* see brssl.h */\n+const br_hash_class *\n+get_hash_impl(int hash_id)\n+{\n+\tsize_t u;\n+\n+\tfor (u \u003d 0; hash_functions[u].name; u ++) {\n+\t\tconst br_hash_class *hc;\n+\t\tint id;\n+\n+\t\thc \u003d hash_functions[u].hclass;\n+\t\tid \u003d (hc-\u003edesc \u003e\u003e BR_HASHDESC_ID_OFF) \u0026 BR_HASHDESC_ID_MASK;\n+\t\tif (id \u003d\u003d hash_id) {\n+\t\t\treturn hc;\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\ndiff --git a/tools/names.c b/tools/names.c\nindex 191dfeb..06b2cdb 100644\n--- a/tools/names.c\n+++ b/tools/names.c\n@@ -651,3 +651,20 @@ ec_curve_name(int curve)\n \t\treturn \u0022unknown\u0022;\n \t}\n }\n+\n+/* see brssl.h */\n+const char *\n+hash_function_name(int id)\n+{\n+\tswitch (id) {\n+\tcase br_md5sha1_ID: return \u0022MD5+SHA-1\u0022;\n+\tcase br_md5_ID: return \u0022MD5\u0022;\n+\tcase br_sha1_ID: return \u0022SHA-1\u0022;\n+\tcase br_sha224_ID: return \u0022SHA-224\u0022;\n+\tcase br_sha256_ID: return \u0022SHA-256\u0022;\n+\tcase br_sha384_ID: return \u0022SHA-384\u0022;\n+\tcase br_sha512_ID: return \u0022SHA-512\u0022;\n+\tdefault:\n+\t\treturn \u0022unknown\u0022;\n+\t}\n+}\ndiff --git a/tools/server.c b/tools/server.c\nindex b81ce07..5e9315d 100644\n--- a/tools/server.c\n+++ b/tools/server.c\n@@ -214,6 +214,10 @@ usage_server(void)\n \tfprintf(stderr,\n \u0022 -key fname read private key from file 'fname'\u005cn\u0022);\n \tfprintf(stderr,\n+\u0022 -CA file add trust anchors from 'file' (for client auth)\u005cn\u0022);\n+\tfprintf(stderr,\n+\u0022 -anon_ok request but do not require a client certificate\u005cn\u0022);\n+\tfprintf(stderr,\n \u0022 -list list supported names (protocols, algorithms...)\u005cn\u0022);\n \tfprintf(stderr,\n \u0022 -vmin name set minimum supported version (default: TLS-1.0)\u005cn\u0022);\n@@ -237,20 +241,43 @@ typedef struct {\n \tprivate_key *sk;\n } policy_context;\n \n+static void\n+print_hashes(unsigned chashes)\n+{\n+\tint i;\n+\n+\tfor (i \u003d 2; i \u003c\u003d 6; i ++) {\n+\t\tif ((chashes \u003e\u003e i) \u0026 1) {\n+\t\t\tint z;\n+\n+\t\t\tswitch (i) {\n+\t\t\tcase 3: z \u003d 224; break;\n+\t\t\tcase 4: z \u003d 256; break;\n+\t\t\tcase 5: z \u003d 384; break;\n+\t\t\tcase 6: z \u003d 512; break;\n+\t\t\tdefault:\n+\t\t\t\tz \u003d 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tfprintf(stderr, \u0022 sha%d\u0022, z);\n+\t\t}\n+\t}\n+}\n+\n static int\n-get_cert_signer_algo(br_x509_certificate *xc)\n+choose_hash(unsigned chashes)\n {\n-\tbr_x509_decoder_context dc;\n-\tint err;\n+\tint hash_id;\n \n-\tbr_x509_decoder_init(\u0026dc, 0, 0);\n-\tbr_x509_decoder_push(\u0026dc, xc-\u003edata, xc-\u003edata_len);\n-\terr \u003d br_x509_decoder_last_error(\u0026dc);\n-\tif (err !\u003d 0) {\n-\t\treturn -err;\n-\t} else {\n-\t\treturn br_x509_decoder_get_signer_key_type(\u0026dc);\n+\tfor (hash_id \u003d 6; hash_id \u003e\u003d 2; hash_id --) {\n+\t\tif (((chashes \u003e\u003e hash_id) \u0026 1) !\u003d 0) {\n+\t\t\treturn hash_id;\n+\t\t}\n \t}\n+\t/*\n+\t * Normally unreachable.\n+\t */\n+\treturn 0;\n }\n \n static int\n@@ -262,16 +289,10 @@ sp_choose(const br_ssl_server_policy_class **pctx,\n \tconst br_suite_translated *st;\n \tsize_t u, st_num;\n \tunsigned chashes;\n-\tint hash_id;\n \n \tpc \u003d (policy_context *)pctx;\n \tst \u003d br_ssl_server_get_client_suites(cc, \u0026st_num);\n \tchashes \u003d br_ssl_server_get_client_hashes(cc);\n-\tfor (hash_id \u003d 6; hash_id \u003e\u003d 2; hash_id --) {\n-\t\tif ((chashes \u003e\u003e hash_id) \u0026 1) {\n-\t\t\tbreak;\n-\t\t}\n-\t}\n \tif (pc-\u003everbose) {\n \t\tfprintf(stderr, \u0022Client parameters:\u005cn\u0022);\n \t\tfprintf(stderr, \u0022 Maximum version: \u0022);\n@@ -301,24 +322,17 @@ sp_choose(const br_ssl_server_policy_class **pctx,\n \t\t\tget_suite_name_ext(st[u][0], csn, sizeof csn);\n \t\t\tfprintf(stderr, \u0022 %s\u005cn\u0022, csn);\n \t\t}\n-\t\tfprintf(stderr, \u0022 Common hash functions:\u0022);\n-\t\tfor (u \u003d 2; u \u003c\u003d 6; u ++) {\n-\t\t\tif ((chashes \u003e\u003e u) \u0026 1) {\n-\t\t\t\tint z;\n-\n-\t\t\t\tswitch (u) {\n-\t\t\t\tcase 3: z \u003d 224; break;\n-\t\t\t\tcase 4: z \u003d 256; break;\n-\t\t\t\tcase 5: z \u003d 384; break;\n-\t\t\t\tcase 6: z \u003d 512; break;\n-\t\t\t\tdefault:\n-\t\t\t\t\tz \u003d 1;\n-\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t\tfprintf(stderr, \u0022 sha%d\u0022, z);\n-\t\t\t}\n+\t\tfprintf(stderr, \u0022 Common sign+hash functions:\u005cn\u0022);\n+\t\tif ((chashes \u0026 0xFF) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022 with RSA:\u0022);\n+\t\t\tprint_hashes(chashes);\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n+\t\t}\n+\t\tif ((chashes \u003e\u003e 8) !\u003d 0) {\n+\t\t\tfprintf(stderr, \u0022 with ECDSA:\u0022);\n+\t\t\tprint_hashes(chashes \u003e\u003e 8);\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n \t\t}\n-\t\tfprintf(stderr, \u0022\u005cn\u0022);\n \t}\n \tfor (u \u003d 0; u \u003c st_num; u ++) {\n \t\tunsigned tt;\n@@ -337,9 +351,10 @@ sp_choose(const br_ssl_server_policy_class **pctx,\n \t\t\t\tif (br_ssl_engine_get_version(\u0026cc-\u003eeng)\n \t\t\t\t\t\u003c BR_TLS12)\n \t\t\t\t{\n-\t\t\t\t\thash_id \u003d 0;\n+\t\t\t\t\tchoices-\u003ehash_id \u003d 0;\n+\t\t\t\t} else {\n+\t\t\t\t\tchoices-\u003ehash_id \u003d choose_hash(chashes);\n \t\t\t\t}\n-\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n \t\t\t\tgoto choose_ok;\n \t\t\t}\n \t\t\tbreak;\n@@ -349,9 +364,11 @@ sp_choose(const br_ssl_server_policy_class **pctx,\n \t\t\t\tif (br_ssl_engine_get_version(\u0026cc-\u003eeng)\n \t\t\t\t\t\u003c BR_TLS12)\n \t\t\t\t{\n-\t\t\t\t\thash_id \u003d br_sha1_ID;\n+\t\t\t\t\tchoices-\u003ehash_id \u003d br_sha1_ID;\n+\t\t\t\t} else {\n+\t\t\t\t\tchoices-\u003ehash_id \u003d\n+\t\t\t\t\t\tchoose_hash(chashes \u003e\u003e 8);\n \t\t\t\t}\n-\t\t\t\tchoices-\u003ehash_id \u003d hash_id;\n \t\t\t\tgoto choose_ok;\n \t\t\t}\n \t\t\tbreak;\n@@ -409,55 +426,6 @@ sp_do_keyx(const br_ssl_server_policy_class **pctx,\n \t}\n }\n \n-/*\n- * OID for hash functions in RSA signatures.\n- */\n-static const unsigned char HASH_OID_SHA1[] \u003d {\n-\t0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A\n-};\n-\n-static const unsigned char HASH_OID_SHA224[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04\n-};\n-\n-static const unsigned char HASH_OID_SHA256[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01\n-};\n-\n-static const unsigned char HASH_OID_SHA384[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02\n-};\n-\n-static const unsigned char HASH_OID_SHA512[] \u003d {\n-\t0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03\n-};\n-\n-static const unsigned char *HASH_OID[] \u003d {\n-\tHASH_OID_SHA1,\n-\tHASH_OID_SHA224,\n-\tHASH_OID_SHA256,\n-\tHASH_OID_SHA384,\n-\tHASH_OID_SHA512\n-};\n-\n-static const br_hash_class *\n-get_hash_impl(int hash_id)\n-{\n-\tsize_t u;\n-\n-\tfor (u \u003d 0; hash_functions[u].name; u ++) {\n-\t\tconst br_hash_class *hc;\n-\t\tint id;\n-\n-\t\thc \u003d hash_functions[u].hclass;\n-\t\tid \u003d (hc-\u003edesc \u003e\u003e BR_HASHDESC_ID_OFF) \u0026 BR_HASHDESC_ID_MASK;\n-\t\tif (id \u003d\u003d hash_id) {\n-\t\t\treturn hc;\n-\t\t}\n-\t}\n-\treturn NULL;\n-}\n-\n static size_t\n sp_do_sign(const br_ssl_server_policy_class **pctx,\n \tint hash_id, size_t hv_len, unsigned char *data, size_t len)\n@@ -474,11 +442,8 @@ sp_do_sign(const br_ssl_server_policy_class **pctx,\n \t\tconst br_hash_class *hc;\n \n \tcase BR_KEYTYPE_RSA:\n-\t\tif (hash_id \u003d\u003d 0) {\n-\t\t\thash_oid \u003d NULL;\n-\t\t} else if (hash_id \u003e\u003d 2 \u0026\u0026 hash_id \u003c\u003d 6) {\n-\t\t\thash_oid \u003d HASH_OID[hash_id - 2];\n-\t\t} else {\n+\t\thash_oid \u003d get_hash_oid(hash_id);\n+\t\tif (hash_oid \u003d\u003d NULL \u0026\u0026 hash_id !\u003d 0) {\n \t\t\tif (pc-\u003everbose) {\n \t\t\t\tfprintf(stderr, \u0022ERROR: cannot RSA-sign with\u0022\n \t\t\t\t\t\u0022 unknown hash function: %d\u005cn\u0022,\n@@ -566,6 +531,9 @@ do_server(int argc, char *argv[])\n \tsize_t chain_len;\n \tint cert_signer_algo;\n \tprivate_key *sk;\n+\tanchor_list anchors \u003d VEC_INIT;\n+\tbr_x509_minimal_context xc;\n+\tconst br_hash_class *dnhash;\n \tsize_t u;\n \tbr_ssl_server_context cc;\n \tpolicy_context pc;\n@@ -713,6 +681,20 @@ do_server(int argc, char *argv[])\n \t\t\tif (sk \u003d\u003d NULL) {\n \t\t\t\tgoto server_exit_error;\n \t\t\t}\n+\t\t} else if (eqstr(arg, \u0022-CA\u0022)) {\n+\t\t\tif (++ i \u003e\u003d argc) {\n+\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t\u0022ERROR: no argument for '-CA'\u005cn\u0022);\n+\t\t\t\tusage_server();\n+\t\t\t\tgoto server_exit_error;\n+\t\t\t}\n+\t\t\targ \u003d argv[i];\n+\t\t\tif (read_trust_anchors(\u0026anchors, arg) \u003d\u003d 0) {\n+\t\t\t\tusage_server();\n+\t\t\t\tgoto server_exit_error;\n+\t\t\t}\n+\t\t} else if (eqstr(arg, \u0022-anon_ok\u0022)) {\n+\t\t\tflags |\u003d BR_OPT_TOLERATE_NO_CLIENT_AUTH;\n \t\t} else if (eqstr(arg, \u0022-list\u0022)) {\n \t\t\tlist_names();\n \t\t\tgoto server_exit;\n@@ -872,11 +854,10 @@ do_server(int argc, char *argv[])\n \t\tbreak;\n \t}\n \tcert_signer_algo \u003d get_cert_signer_algo(chain);\n-\tif (cert_signer_algo \u003c 0) {\n-\t\tfprintf(stderr, \u0022ERROR: server certificate cannot be\u0022\n-\t\t\t\u0022 decoded (err\u003d%d)\u005cn\u0022, -cert_signer_algo);\n+\tif (cert_signer_algo \u003d\u003d 0) {\n \t\tgoto server_exit_error;\n-\t} else if (verbose) {\n+\t}\n+\tif (verbose) {\n \t\tconst char *csas;\n \n \t\tswitch (cert_signer_algo) {\n@@ -980,6 +961,7 @@ do_server(int argc, char *argv[])\n \t}\n \tbr_ssl_engine_set_suites(\u0026cc.eng, suite_ids, num_suites);\n \n+\tdnhash \u003d NULL;\n \tfor (u \u003d 0; hash_functions[u].name; u ++) {\n \t\tconst br_hash_class *hc;\n \t\tint id;\n@@ -987,6 +969,7 @@ do_server(int argc, char *argv[])\n \t\thc \u003d hash_functions[u].hclass;\n \t\tid \u003d (hc-\u003edesc \u003e\u003e BR_HASHDESC_ID_OFF) \u0026 BR_HASHDESC_ID_MASK;\n \t\tif ((hfuns \u0026 ((unsigned)1 \u003c\u003c id)) !\u003d 0) {\n+\t\t\tdnhash \u003d hc;\n \t\t\tbr_ssl_engine_set_hash(\u0026cc.eng, id, hc);\n \t\t}\n \t}\n@@ -1007,6 +990,11 @@ do_server(int argc, char *argv[])\n \tbr_ssl_session_cache_lru_init(\u0026lru, cache, cache_len);\n \tbr_ssl_server_set_cache(\u0026cc, \u0026lru.vtable);\n \n+\t/*\n+\t * Set the policy handler (that chooses the actual cipher suite,\n+\t * selects the certificate chain, and runs the private key\n+\t * operations).\n+\t */\n \tpc.vtable \u003d \u0026policy_vtable;\n \tpc.verbose \u003d verbose;\n \tpc.chain \u003d chain;\n@@ -1015,6 +1003,36 @@ do_server(int argc, char *argv[])\n \tpc.sk \u003d sk;\n \tbr_ssl_server_set_policy(\u0026cc, \u0026pc.vtable);\n \n+\t/*\n+\t * If trust anchors have been configured, then set an X.509\n+\t * validation engine and activate client certificate\n+\t * authentication.\n+\t */\n+\tif (VEC_LEN(anchors) !\u003d 0) {\n+\t\tbr_x509_minimal_init(\u0026xc, dnhash,\n+\t\t\t\u0026VEC_ELT(anchors, 0), VEC_LEN(anchors));\n+\t\tfor (u \u003d 0; hash_functions[u].name; u ++) {\n+\t\t\tconst br_hash_class *hc;\n+\t\t\tint id;\n+\n+\t\t\thc \u003d hash_functions[u].hclass;\n+\t\t\tid \u003d (hc-\u003edesc \u003e\u003e BR_HASHDESC_ID_OFF)\n+\t\t\t\t\u0026 BR_HASHDESC_ID_MASK;\n+\t\t\tif ((hfuns \u0026 ((unsigned)1 \u003c\u003c id)) !\u003d 0) {\n+\t\t\t\tbr_x509_minimal_set_hash(\u0026xc, id, hc);\n+\t\t\t}\n+\t\t}\n+\t\tbr_ssl_engine_set_rsavrfy(\u0026cc.eng, \u0026br_rsa_i31_pkcs1_vrfy);\n+\t\tbr_ssl_engine_set_ec(\u0026cc.eng, \u0026br_ec_prime_i31);\n+\t\tbr_ssl_engine_set_ecdsa(\u0026cc.eng, \u0026br_ecdsa_i31_vrfy_asn1);\n+\t\tbr_x509_minimal_set_rsa(\u0026xc, \u0026br_rsa_i31_pkcs1_vrfy);\n+\t\tbr_x509_minimal_set_ecdsa(\u0026xc,\n+\t\t\t\u0026br_ec_prime_i31, \u0026br_ecdsa_i31_vrfy_asn1);\n+\t\tbr_ssl_engine_set_x509(\u0026cc.eng, \u0026xc.vtable);\n+\t\tbr_ssl_server_set_trust_anchor_names_alt(\u0026cc,\n+\t\t\t\u0026VEC_ELT(anchors, 0), VEC_LEN(anchors));\n+\t}\n+\n \tbr_ssl_engine_set_buffer(\u0026cc.eng, iobuf, iobuf_len, bidi);\n \n \t/*\n@@ -1061,13 +1079,9 @@ do_server(int argc, char *argv[])\n server_exit:\n \txfree(suites);\n \txfree(suite_ids);\n-\tif (chain !\u003d NULL) {\n-\t\tfor (u \u003d 0; u \u003c chain_len; u ++) {\n-\t\t\txfree(chain[u].data);\n-\t\t}\n-\t\txfree(chain);\n-\t}\n+\tfree_certificates(chain, chain_len);\n \tfree_private_key(sk);\n+\tVEC_CLEAREXT(anchors, \u0026free_ta_contents);\n \txfree(iobuf);\n \txfree(cache);\n \tif (fd \u003e\u003d 0) {\ndiff --git a/tools/ta.c b/tools/ta.c\nindex a29aae0..df72e2b 100644\n--- a/tools/ta.c\n+++ b/tools/ta.c\n@@ -93,7 +93,7 @@ print_ta_internals(br_x509_trust_anchor *ta, long ctr)\n \tchar tmp[25];\n \n \tsprintf(tmp, \u0022TA%ld_DN\u0022, ctr);\n-\tprint_blob(tmp, ta-\u003edn, ta-\u003edn_len);\n+\tprint_blob(tmp, ta-\u003edn.data, ta-\u003edn.len);\n \tswitch (ta-\u003epkey.key_type) {\n \tcase BR_KEYTYPE_RSA:\n \t\tsprintf(tmp, \u0022TA%ld_RSA_N\u0022, ctr);\n@@ -119,7 +119,8 @@ print_ta(br_x509_trust_anchor *ta, long ctr)\n \tchar tmp[25];\n \n \tprintf(\u0022\u005ct{\u005cn\u0022);\n-\tprintf(\u0022\u005ct\u005ct(unsigned char *)TA%ld_DN, sizeof TA%ld_DN,\u005cn\u0022, ctr, ctr);\n+\tprintf(\u0022\u005ct\u005ct{ (unsigned char *)TA%ld_DN, sizeof TA%ld_DN },\u005cn\u0022,\n+\t\tctr, ctr);\n \tprintf(\u0022\u005ct\u005ct%s,\u005cn\u0022, (ta-\u003eflags \u0026 BR_X509_TA_CA)\n \t\t? \u0022BR_X509_TA_CA\u0022 : \u00220\u0022);\n \tprintf(\u0022\u005ct\u005ct{\u005cn\u0022);\ndiff --git a/tools/verify.c b/tools/verify.c\nindex 064a61f..7405578 100644\n--- a/tools/verify.c\n+++ b/tools/verify.c\n@@ -181,9 +181,11 @@ do_verify(int argc, char *argv[])\n \tcert_list chain \u003d VEC_INIT;\n \tsize_t u;\n \tbr_x509_minimal_context mc;\n-\tint err_keyx, err_sign;\n+\tint err;\n \tint print_text, print_C;\n \tbr_x509_pkey *pk;\n+\tconst br_x509_pkey *tpk;\n+\tunsigned usages;\n \n \tretcode \u003d 0;\n \tverbose \u003d 1;\n@@ -191,8 +193,6 @@ do_verify(int argc, char *argv[])\n \tprint_text \u003d 0;\n \tprint_C \u003d 0;\n \tpk \u003d NULL;\n-\terr_keyx \u003d 0;\n-\terr_sign \u003d 0;\n \tfor (i \u003d 0; i \u003c argc; i ++) {\n \t\tconst char *arg;\n \n@@ -266,55 +266,44 @@ do_verify(int argc, char *argv[])\n \tbr_x509_minimal_set_rsa(\u0026mc, \u0026br_rsa_i31_pkcs1_vrfy);\n \tbr_x509_minimal_set_ecdsa(\u0026mc,\n \t\t\u0026br_ec_prime_i31, \u0026br_ecdsa_i31_vrfy_asn1);\n-\tfor (i \u003d 0; i \u003c 2; i ++) {\n-\t\tconst br_x509_pkey *tpk;\n-\t\tint err;\n \n-\t\tmc.vtable-\u003estart_chain(\u0026mc.vtable,\n-\t\t\ti \u003d\u003d 0 ? BR_KEYTYPE_KEYX : BR_KEYTYPE_SIGN, sni);\n-\t\tfor (u \u003d 0; u \u003c VEC_LEN(chain); u ++) {\n-\t\t\tbr_x509_certificate *xc;\n+\tmc.vtable-\u003estart_chain(\u0026mc.vtable, sni);\n+\tfor (u \u003d 0; u \u003c VEC_LEN(chain); u ++) {\n+\t\tbr_x509_certificate *xc;\n \n-\t\t\txc \u003d \u0026VEC_ELT(chain, u);\n-\t\t\tmc.vtable-\u003estart_cert(\u0026mc.vtable, xc-\u003edata_len);\n-\t\t\tmc.vtable-\u003eappend(\u0026mc.vtable, xc-\u003edata, xc-\u003edata_len);\n-\t\t\tmc.vtable-\u003eend_cert(\u0026mc.vtable);\n-\t\t}\n-\t\terr \u003d mc.vtable-\u003eend_chain(\u0026mc.vtable);\n-\t\tif (i \u003d\u003d 0) {\n-\t\t\terr_keyx \u003d err;\n-\t\t} else {\n-\t\t\terr_sign \u003d err;\n-\t\t}\n-\t\ttpk \u003d mc.vtable-\u003eget_pkey(\u0026mc.vtable);\n-\t\tif (pk \u003d\u003d NULL \u0026\u0026 tpk !\u003d NULL) {\n-\t\t\tpk \u003d xpkeydup(tpk);\n-\t\t}\n+\t\txc \u003d \u0026VEC_ELT(chain, u);\n+\t\tmc.vtable-\u003estart_cert(\u0026mc.vtable, xc-\u003edata_len);\n+\t\tmc.vtable-\u003eappend(\u0026mc.vtable, xc-\u003edata, xc-\u003edata_len);\n+\t\tmc.vtable-\u003eend_cert(\u0026mc.vtable);\n+\t}\n+\terr \u003d mc.vtable-\u003eend_chain(\u0026mc.vtable);\n+\ttpk \u003d mc.vtable-\u003eget_pkey(\u0026mc.vtable, \u0026usages);\n+\tif (tpk !\u003d NULL) {\n+\t\tpk \u003d xpkeydup(tpk);\n \t}\n-\tif (err_keyx \u003d\u003d 0 || err_sign \u003d\u003d 0) {\n+\n+\tif (err \u003d\u003d 0) {\n \t\tif (verbose) {\n-\t\t\tfprintf(stderr, \u0022Validation success\u0022);\n-\t\t\tif (err_keyx \u003d\u003d 0 \u0026\u0026 err_sign \u003d\u003d 0) {\n-\t\t\t\tfprintf(stderr, \u0022 (key exchange, sign)\u005cn\u0022);\n-\t\t\t} else if (err_keyx \u003d\u003d 0) {\n-\t\t\t\tfprintf(stderr, \u0022 (key exchange)\u005cn\u0022);\n-\t\t\t} else if (err_sign \u003d\u003d 0) {\n-\t\t\t\tfprintf(stderr, \u0022 (signature)\u005cn\u0022);\n+\t\t\tint hkx;\n+\n+\t\t\tfprintf(stderr, \u0022Validation success; usages:\u0022);\n+\t\t\thkx \u003d 0;\n+\t\t\tif (usages \u0026 BR_KEYTYPE_KEYX) {\n+\t\t\t\tfprintf(stderr, \u0022 key exchange\u0022);\n+\t\t\t\thkx \u003d 1;\n \t\t\t}\n+\t\t\tif (usages \u0026 BR_KEYTYPE_SIGN) {\n+\t\t\t\tif (hkx) {\n+\t\t\t\t\tfprintf(stderr, \u0022,\u0022);\n+\t\t\t\t}\n+\t\t\t\tfprintf(stderr, \u0022 signature\u0022);\n+\t\t\t}\n+\t\t\tfprintf(stderr, \u0022\u005cn\u0022);\n \t\t}\n \t} else {\n \t\tif (verbose) {\n-\t\t\tint err;\n \t\t\tconst char *errname, *errmsg;\n \n-\t\t\t/*\n-\t\t\t * If the two error codes differ, we want the one\n-\t\t\t * which is not a \u0022forbidden key usage\u0022.\n-\t\t\t */\n-\t\t\terr \u003d err_keyx;\n-\t\t\tif (err \u003d\u003d BR_ERR_X509_FORBIDDEN_KEY_USAGE) {\n-\t\t\t\terr \u003d err_sign;\n-\t\t\t}\n \t\t\tfprintf(stderr, \u0022Validation failed, err \u003d %d\u0022, err);\n \t\t\terrname \u003d find_error_name(err, \u0026errmsg);\n \t\t\tif (errname !\u003d NULL) {\n","s":{"c":1745563261,"u": 31979}}
],"g": 112326,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}