Added support for client certificates (both client-side and server-side, but still...
authorThomas Pornin <pornin@bolet.org>
Sat, 10 Dec 2016 16:35:06 +0000 (17:35 +0100)
committerThomas Pornin <pornin@bolet.org>
Sat, 10 Dec 2016 16:35:06 +0000 (17:35 +0100)
27 files changed:
Makefile
inc/bearssl_ssl.h
inc/bearssl_x509.h
src/ssl/ssl_ccert_single_ec.c [new file with mode: 0644]
src/ssl/ssl_ccert_single_rsa.c [new file with mode: 0644]
src/ssl/ssl_client_full.c
src/ssl/ssl_hs_client.c
src/ssl/ssl_hs_client.t0
src/ssl/ssl_hs_common.t0
src/ssl/ssl_hs_server.c
src/ssl/ssl_hs_server.t0
src/ssl/ssl_scert_single_ec.c [moved from src/ssl/ssl_single_ec.c with 99% similarity]
src/ssl/ssl_scert_single_rsa.c [moved from src/ssl/ssl_single_rsa.c with 100% similarity]
src/x509/x509_knownkey.c
src/x509/x509_minimal.c
src/x509/x509_minimal.t0
test/test_x509.c
tools/brssl.h
tools/certs.c
tools/client.c
tools/errors.c
tools/files.c
tools/keys.c
tools/names.c
tools/server.c
tools/ta.c
tools/verify.c

index 5eabd31..57a0867 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ OBJINT32 = $(BUILD)/i32_add.o $(BUILD)/i32_bitlen.o $(BUILD)/i32_decmod.o $(BUIL
 OBJMAC = $(BUILD)/hmac.o $(BUILD)/hmac_ct.o
 OBJRAND = $(BUILD)/hmac_drbg.o
 OBJRSA = $(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
 OBJMAC = $(BUILD)/hmac.o $(BUILD)/hmac_ct.o
 OBJRAND = $(BUILD)/hmac_drbg.o
 OBJRSA = $(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
-OBJSSL = $(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
+OBJSSL = $(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
 OBJSYMCIPHER = $(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
 OBJX509 = $(BUILD)/skey_decoder.o $(BUILD)/x509_decoder.o $(BUILD)/x509_knownkey.o $(BUILD)/x509_minimal.o
 OBJ = $(OBJCODEC) $(OBJEC) $(OBJHASH) $(OBJINT31) $(OBJINT32) $(OBJMAC) $(OBJRAND) $(OBJRSA) $(OBJSSL) $(OBJSYMCIPHER) $(OBJX509)
 OBJSYMCIPHER = $(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
 OBJX509 = $(BUILD)/skey_decoder.o $(BUILD)/x509_decoder.o $(BUILD)/x509_knownkey.o $(BUILD)/x509_minimal.o
 OBJ = $(OBJCODEC) $(OBJEC) $(OBJHASH) $(OBJINT31) $(OBJINT32) $(OBJMAC) $(OBJRAND) $(OBJRSA) $(OBJSSL) $(OBJSYMCIPHER) $(OBJX509)
@@ -386,6 +386,12 @@ $(BUILD)/prf_sha256.o: src/ssl/prf_sha256.c $(HEADERS)
 $(BUILD)/prf_sha384.o: src/ssl/prf_sha384.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/prf_sha384.o src/ssl/prf_sha384.c
 
 $(BUILD)/prf_sha384.o: src/ssl/prf_sha384.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/prf_sha384.o src/ssl/prf_sha384.c
 
+$(BUILD)/ssl_ccert_single_ec.o: src/ssl/ssl_ccert_single_ec.c $(HEADERS)
+       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_ccert_single_ec.o src/ssl/ssl_ccert_single_ec.c
+
+$(BUILD)/ssl_ccert_single_rsa.o: src/ssl/ssl_ccert_single_rsa.c $(HEADERS)
+       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_ccert_single_rsa.o src/ssl/ssl_ccert_single_rsa.c
+
 $(BUILD)/ssl_client.o: src/ssl/ssl_client.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_client.o src/ssl/ssl_client.c
 
 $(BUILD)/ssl_client.o: src/ssl/ssl_client.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_client.o src/ssl/ssl_client.c
 
@@ -440,11 +446,11 @@ $(BUILD)/ssl_server_full_ec.o: src/ssl/ssl_server_full_ec.c $(HEADERS)
 $(BUILD)/ssl_server_full_rsa.o: src/ssl/ssl_server_full_rsa.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_full_rsa.o src/ssl/ssl_server_full_rsa.c
 
 $(BUILD)/ssl_server_full_rsa.o: src/ssl/ssl_server_full_rsa.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_full_rsa.o src/ssl/ssl_server_full_rsa.c
 
-$(BUILD)/ssl_single_ec.o: src/ssl/ssl_single_ec.c $(HEADERS)
-       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_ec.o src/ssl/ssl_single_ec.c
+$(BUILD)/ssl_scert_single_ec.o: src/ssl/ssl_scert_single_ec.c $(HEADERS)
+       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_scert_single_ec.o src/ssl/ssl_scert_single_ec.c
 
 
-$(BUILD)/ssl_single_rsa.o: src/ssl/ssl_single_rsa.c $(HEADERS)
-       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_rsa.o src/ssl/ssl_single_rsa.c
+$(BUILD)/ssl_scert_single_rsa.o: src/ssl/ssl_scert_single_rsa.c $(HEADERS)
+       $(CC) $(CFLAGS) -c -o $(BUILD)/ssl_scert_single_rsa.o src/ssl/ssl_scert_single_rsa.c
 
 $(BUILD)/aes_big_cbcdec.o: src/symcipher/aes_big_cbcdec.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_cbcdec.o src/symcipher/aes_big_cbcdec.c
 
 $(BUILD)/aes_big_cbcdec.o: src/symcipher/aes_big_cbcdec.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_cbcdec.o src/symcipher/aes_big_cbcdec.c
index 463e616..b038500 100644 (file)
     signature algorithm, hash function). */
 #define BR_ERR_INVALID_ALGORITHM      26
 
     signature algorithm, hash function). */
 #define BR_ERR_INVALID_ALGORITHM      26
 
-/** \brief SSL status: invalid signature on ServerKeyExchange message. */
+/** \brief SSL status: invalid signature (on ServerKeyExchange from
+    server, or in CertificateVerify from client). */
 #define BR_ERR_BAD_SIGNATURE          27
 
 #define BR_ERR_BAD_SIGNATURE          27
 
+/** \brief SSL status: peer's public key does not have the proper type
+    or is not allowed for requested operation. */
+#define BR_ERR_WRONG_KEY_USAGE        28
+
+/** \brief SSL status: client did not send a certificate upon request,
+    or the client certificate could not be validated. */
+#define BR_ERR_NO_CLIENT_AUTH         29
+
 /** \brief SSL status: I/O error or premature close on underlying
     transport stream. This error code is set only by the simplified
     I/O API ("br_sslio_*"). */
 /** \brief SSL status: I/O error or premature close on underlying
     transport stream. This error code is set only by the simplified
     I/O API ("br_sslio_*"). */
@@ -769,12 +778,11 @@ typedef struct {
        uint32_t flags;
 
        /*
        uint32_t flags;
 
        /*
-        * Context variables for the handshake processor.
-        * The 'pad' must be large enough to accommodate an
-        * RSA-encrypted pre-master secret, or a RSA signature on
-        * key exchange parameters; since we want to support up to
-        * RSA-4096, this means at least 512 bytes.
-        * (Other pad usages require its length to be at least 256.)
+        * Context variables for the handshake processor. The 'pad' must
+        * be large enough to accommodate an RSA-encrypted pre-master
+        * secret, or an RSA signature; since we want to support up to
+        * RSA-4096, this means at least 512 bytes. (Other pad usages
+        * require its length to be at least 256.)
         */
        struct {
                uint32_t *dp;
         */
        struct {
                uint32_t *dp;
@@ -825,6 +833,16 @@ typedef struct {
         */
        const br_x509_class **x509ctx;
 
         */
        const br_x509_class **x509ctx;
 
+       /*
+        * Certificate chain to send. This is used by both client and
+        * server, when they send their respective Certificate messages.
+        * If chain_len is 0, then chain may be NULL.
+        */
+       const br_x509_certificate *chain;
+       size_t chain_len;
+       const unsigned char *cert_cur;
+       size_t cert_len;
+
        /*
         * Pointers to implementations; left to NULL for unsupported
         * functions. For the raw hash functions, implementations are
        /*
         * Pointers to implementations; left to NULL for unsupported
         * functions. For the raw hash functions, implementations are
@@ -844,6 +862,8 @@ typedef struct {
        const br_sslrec_in_gcm_class *igcm_in;
        const br_sslrec_out_gcm_class *igcm_out;
        const br_ec_impl *iec;
        const br_sslrec_in_gcm_class *igcm_in;
        const br_sslrec_out_gcm_class *igcm_out;
        const br_ec_impl *iec;
+       br_rsa_pkcs1_vrfy irsavrfy;
+       br_ecdsa_vrfy iecdsa;
 #endif
 } br_ssl_engine_context;
 
 #endif
 } br_ssl_engine_context;
 
@@ -909,7 +929,7 @@ br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
  */
 #define BR_OPT_ENFORCE_SERVER_PREFERENCES      ((uint32_t)1 << 0)
 
  */
 #define BR_OPT_ENFORCE_SERVER_PREFERENCES      ((uint32_t)1 << 0)
 
-/*
+/**
  * \brief Behavioural flag: disable renegotiation.
  *
  * If this flag is set, then renegotiations are rejected unconditionally:
  * \brief Behavioural flag: disable renegotiation.
  *
  * If this flag is set, then renegotiations are rejected unconditionally:
@@ -918,6 +938,26 @@ br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
  */
 #define BR_OPT_NO_RENEGOTIATION                ((uint32_t)1 << 1)
 
  */
 #define BR_OPT_NO_RENEGOTIATION                ((uint32_t)1 << 1)
 
+/**
+ * \brief Behavioural flag: tolerate lack of client authentication.
+ *
+ * If this flag is set in a server and the server requests a client
+ * certificate, but the authentication fails (the client does not send
+ * a certificate, or the client's certificate chain cannot be validated),
+ * then the connection keeps on. Without this flag, a failed client
+ * authentication terminates the connection.
+ *
+ * Notes:
+ *
+ *   - If the client's certificate can be validated and its public key is
+ *     supported, then a wrong signature value terminates the connection
+ *     regardless of that flag.
+ *
+ *   - If using full-static ECDH, then a failure to validate the client's
+ *     certificate prevents the handshake from succeeding.
+ */
+#define BR_OPT_TOLERATE_NO_CLIENT_AUTH         ((uint32_t)1 << 2)
+
 /**
  * \brief Set the minimum and maximum supported protocol versions.
  *
 /**
  * \brief Set the minimum and maximum supported protocol versions.
  *
@@ -1157,6 +1197,44 @@ br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
        cc->iec = iec;
 }
 
        cc->iec = iec;
 }
 
+/**
+ * \brief Set the RSA signature verification implementation.
+ *
+ * On the client, this is used to verify the server's signature on its
+ * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server,
+ * this is used to verify the client's CertificateVerify message (if a
+ * client certificate is requested, and that certificate contains a RSA key).
+ *
+ * \param cc         SSL engine context.
+ * \param irsavrfy   RSA signature verification implementation.
+ */
+static inline void
+br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
+{
+       cc->irsavrfy = irsavrfy;
+}
+
+/*
+ * \brief Set the ECDSA implementation (signature verification).
+ *
+ * On the client, this is used to verify the server's signature on its
+ * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server,
+ * this is used to verify the client's CertificateVerify message (if a
+ * client certificate is requested, that certificate contains an EC key,
+ * and full-static ECDH is not used).
+ *
+ * The ECDSA implementation will use the EC core implementation configured
+ * in the engine context.
+ *
+ * \param cc       client context.
+ * \param iecdsa   ECDSA verification implementation.
+ */
+static inline void
+br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa)
+{
+       cc->iecdsa = iecdsa;
+}
+
 /**
  * \brief Set the I/O buffer for the SSL engine.
  *
 /**
  * \brief Set the I/O buffer for the SSL engine.
  *
@@ -1597,6 +1675,326 @@ void br_ssl_engine_close(br_ssl_engine_context *cc);
  */
 int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
 
  */
 int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
 
+/*
+ * Pre-declaration for the SSL client context.
+ */
+typedef struct br_ssl_client_context_ br_ssl_client_context;
+
+/**
+ * \brief Type for the client certificate, if requested by the server.
+ */
+typedef struct {
+       /**
+        * \brief Authentication type.
+        *
+        * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA`
+        * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange).
+        */
+       int auth_type;
+
+       /**
+        * \brief Hash function for computing the CertificateVerify.
+        *
+        * This is the symbolic identifier for the hash function that
+        * will be used to produce the hash of handshake messages, to
+        * be signed into the CertificateVerify. For full static ECDH
+        * (client and server certificates are both EC in the same
+        * curve, and static ECDH is used), this value is set to -1.
+        *
+        * Take care that with TLS 1.0 and 1.1, that value MUST match
+        * the protocol requirements: value must be 0 (MD5+SHA-1) for
+        * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only
+        * TLS 1.2 allows for other hash functions.
+        */
+       int hash_id;
+
+       /**
+        * \brief Certificate chain to send to the server.
+        *
+        * This is an array of `br_x509_certificate` objects, each
+        * normally containing a DER-encoded certificate. The client
+        * code does not try to decode these elements. If there is no
+        * chain to send to the server, then this pointer shall be
+        * set to `NULL`.
+        */
+       const br_x509_certificate *chain;
+
+       /**
+        * \brief Certificate chain length (number of certificates).
+        *
+        * If there is no chain to send to the server, then this value
+        * shall be set to 0.
+        */
+       size_t chain_len;
+
+} br_ssl_client_certificate;
+
+/*
+ * Note: the constants below for signatures match the TLS constants.
+ */
+
+/** \brief Client authentication type: static ECDH. */
+#define BR_AUTH_ECDH    0
+/** \brief Client authentication type: RSA signature. */
+#define BR_AUTH_RSA     1
+/** \brief Client authentication type: ECDSA signature. */
+#define BR_AUTH_ECDSA   3
+
+/**
+ * \brief Class type for a certificate handler (client side).
+ *
+ * A certificate handler selects a client certificate chain to send to
+ * the server, upon explicit request from that server. It receives
+ * the list of trust anchor DN from the server, and supported types
+ * of certificates and signatures, and returns the chain to use. It
+ * is also invoked to perform the corresponding private key operation
+ * (a signature, or an ECDH computation).
+ *
+ * The SSL client engine will first push the trust anchor DN with
+ * `start_name_list()`, `start_name()`, `append_name()`, `end_name()`
+ * and `end_name_list()`. Then it will call `choose()`, to select the
+ * actual chain (and signature/hash algorithms). Finally, it will call
+ * either `do_sign()` or `do_keyx()`, depending on the algorithm choices.
+ */
+typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class;
+struct br_ssl_client_certificate_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
+       size_t context_size;
+
+       /**
+        * \brief Begin reception of a list of trust anchor names. This
+        * is called while parsing the incoming CertificateRequest.
+        *
+        * \param pctx   certificate handler context.
+        */
+       void (*start_name_list)(const br_ssl_client_certificate_class **pctx);
+
+       /**
+        * \brief Begin reception of a new trust anchor name.
+        *
+        * The total encoded name length is provided; it is less than
+        * 65535 bytes.
+        *
+        * \param pctx   certificate handler context.
+        * \param len    encoded name length (in bytes).
+        */
+       void (*start_name)(const br_ssl_client_certificate_class **pctx,
+               size_t len);
+
+       /**
+        * \brief Receive some more bytes for the current trust anchor name.
+        *
+        * The provided reference (`data`) points to a transient buffer
+        * they may be reused as soon as this function returns. The chunk
+        * length (`len`) is never zero.
+        *
+        * \param pctx   certificate handler context.
+        * \param data   anchor name chunk.
+        * \param len    anchor name chunk length (in bytes).
+        */
+       void (*append_name)(const br_ssl_client_certificate_class **pctx,
+               const unsigned char *data, size_t len);
+
+       /**
+        * \brief End current trust anchor name.
+        *
+        * This function is called when all the encoded anchor name data
+        * has been provided.
+        *
+        * \param pctx   certificate handler context.
+        */
+       void (*end_name)(const br_ssl_client_certificate_class **pctx);
+
+       /**
+        * \brief End list of trust anchor names.
+        *
+        * This function is called when all the anchor names in the
+        * CertificateRequest message have been obtained.
+        *
+        * \param pctx   certificate handler context.
+        */
+       void (*end_name_list)(const br_ssl_client_certificate_class **pctx);
+
+       /**
+        * \brief Select client certificate and algorithms.
+        *
+        * This callback function shall fill the provided `choices`
+        * structure with the selected algorithms and certificate chain.
+        * The `hash_id`, `chain` and `chain_len` fields must be set. If
+        * the client cannot or does not wish to send a certificate,
+        * then it shall set `chain` to `NULL` and `chain_len` to 0.
+        *
+        * The `auth_types` parameter describes the authentication types,
+        * signature algorithms and hash functions that are supported by
+        * both the client context and the server, and compatible with
+        * the current protocol version. This is a bit field with the
+        * following contents:
+        *
+        *   - If RSA signatures with hash function x are supported, then
+        *     bit x is set.
+        *
+        *   - If ECDSA signatures with hash function x are supported,
+        *     then bit 8+x is set.
+        *
+        *   - If static ECDH is supported, with a RSA-signed certificate,
+        *     then bit 16 is set.
+        *
+        *   - If static ECDH is supported, with an ECDSA-signed certificate,
+        *     then bit 17 is set.
+        *
+        * Notes:
+        *
+        *   - When using TLS 1.0 or 1.1, the hash function for RSA
+        *     signatures is always the special MD5+SHA-1 (id 0), and the
+        *     hash function for ECDSA signatures is always SHA-1 (id 2).
+        *
+        *   - When using TLS 1.2, the list of hash functions is trimmed
+        *     down to include only hash functions that the client context
+        *     can support. The actual server list can be obtained with
+        *     `br_ssl_client_get_server_hashes()`; that list may be used
+        *     to select the certificate chain to send to the server.
+        *
+        * \param pctx         certificate handler context.
+        * \param cc           SSL client context.
+        * \param auth_types   supported authentication types and algorithms.
+        * \param choices      destination structure for the policy choices.
+        */
+       void (*choose)(const br_ssl_client_certificate_class **pctx,
+               const br_ssl_client_context *cc, uint32_t auth_types,
+               br_ssl_client_certificate *choices);
+
+       /**
+        * \brief Perform key exchange (client part).
+        *
+        * This callback is invoked in case of a full static ECDH key
+        * exchange:
+        *
+        *   - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`;
+        *
+        *   - the server requests a client certificate;
+        *
+        *   - the client has, and sends, a client certificate that
+        *     uses an EC key in the same curve as the server's key,
+        *     and chooses static ECDH (the `hash_id` field in the choice
+        *     structure was set to -1).
+        *
+        * In that situation, this callback is invoked to compute the
+        * client-side ECDH: the provided `data` (of length `len` bytes)
+        * is the server's public key point (as decoded from its
+        * certificate), and the client shall multiply that point with
+        * its own private key, and write back the X coordinate of the
+        * resulting point in the same buffer, starting at offset 1
+        * (therefore, writing back the complete encoded point works).
+        *
+        * The callback must uphold the following:
+        *
+        *   - If the input array does not have the proper length for
+        *     an encoded curve point, then an error (0) shall be reported.
+        *
+        *   - If the input array has the proper length, then processing
+        *     MUST be constant-time, even if the data is not a valid
+        *     encoded point.
+        *
+        *   - This callback MUST check that the input point is valid.
+        *
+        * Returned value is 1 on success, 0 on error.
+        *
+        * \param pctx   certificate handler context.
+        * \param data   server public key point.
+        * \param len    server public key point length (in bytes).
+        * \return  1 on success, 0 on error.
+        */
+       uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx,
+               unsigned char *data, size_t len);
+
+       /**
+        * \brief Perform a signature (client authentication).
+        *
+        * This callback is invoked when a client certificate was sent,
+        * and static ECDH is not used. It shall compute a signature,
+        * using the client's private key, over the provided hash value
+        * (which is the hash of all previous handshake messages).
+        *
+        * On input, the hash value to sign is in `data`, of size
+        * `hv_len`; the involved hash function is identified by
+        * `hash_id`. The signature shall be computed and written
+        * back into `data`; the total size of that buffer is `len`
+        * bytes.
+        *
+        * This callback shall verify that the signature length does not
+        * exceed `len` bytes, and abstain from writing the signature if
+        * it does not fit.
+        *
+        * For RSA signatures, the `hash_id` may be 0, in which case
+        * this is the special header-less signature specified in TLS 1.0
+        * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1
+        * v1.5 signatures shall be computed.
+        *
+        * For ECDSA signatures, the signature value shall use the ASN.1
+        * based encoding.
+        *
+        * Returned value is the signature length (in bytes), or 0 on error.
+        *
+        * \param pctx      certificate handler context.
+        * \param hash_id   hash function identifier.
+        * \param hv_len    hash value length (in bytes).
+        * \param data      input/output buffer (hash value, then signature).
+        * \param len       total buffer length (in bytes).
+        * \return  signature length (in bytes) on success, or 0 on error.
+        */
+       size_t (*do_sign)(const br_ssl_client_certificate_class **pctx,
+               int hash_id, size_t hv_len, unsigned char *data, size_t len);
+};
+
+/**
+ * \brief A single-chain RSA client certificate handler.
+ *
+ * This handler uses a single certificate chain, with a RSA
+ * signature. The list of trust anchor DN is ignored.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+       /** \brief Pointer to vtable. */
+       const br_ssl_client_certificate_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+       const br_x509_certificate *chain;
+       size_t chain_len;
+       const br_rsa_private_key *sk;
+       br_rsa_pkcs1_sign irsasign;
+#endif
+} br_ssl_client_certificate_rsa_context;
+
+/**
+ * \brief A single-chain EC client certificate handler.
+ *
+ * This handler uses a single certificate chain, with a RSA
+ * signature. The list of trust anchor DN is ignored.
+ *
+ * This handler may support both static ECDH, and ECDSA signatures
+ * (either usage may be selectively disabled).
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+       /** \brief Pointer to vtable. */
+       const br_ssl_client_certificate_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+       const br_x509_certificate *chain;
+       size_t chain_len;
+       const br_ec_private_key *sk;
+       unsigned allowed_usages;
+       unsigned issuer_key_type;
+       const br_multihash_context *mhash;
+       const br_ec_impl *iec;
+       br_ecdsa_sign iecdsa;
+#endif
+} br_ssl_client_certificate_ec_context;
+
 /**
  * \brief Context structure for a SSL client.
  *
 /**
  * \brief Context structure for a SSL client.
  *
@@ -1605,7 +2003,7 @@ int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
  * a pointer to that field. The other structure fields are opaque and
  * must not be accessed directly.
  */
  * a pointer to that field. The other structure fields are opaque and
  * must not be accessed directly.
  */
-typedef struct {
+struct br_ssl_client_context_ {
        /**
         * \brief The encapsulated engine context.
         */
        /**
         * \brief The encapsulated engine context.
         */
@@ -1620,14 +2018,82 @@ typedef struct {
         */
        uint16_t min_clienthello_len;
 
         */
        uint16_t min_clienthello_len;
 
+       /*
+        * Bit field for algoithms (hash + signature) supported by the
+        * server when requesting a client certificate.
+        */
+       uint16_t hashes;
+
+       /*
+        * Server's public key curve.
+        */
+       int server_curve;
+
+       /*
+        * Context for certificate handler.
+        */
+       const br_ssl_client_certificate_class **client_auth_vtable;
+
+       /*
+        * Client authentication type.
+        */
+       unsigned char auth_type;
+
+       /*
+        * Hash function to use for the client signature. This is 0xFF
+        * if static ECDH is used.
+        */
+       unsigned char hash_id;
+
+       /*
+        * For the core certificate handlers, thus avoiding (in most
+        * cases) the need for an externally provided policy context.
+        */
+       union {
+               const br_ssl_client_certificate_class *vtable;
+               br_ssl_client_certificate_rsa_context single_rsa;
+               br_ssl_client_certificate_ec_context single_ec;
+       } client_auth;
+
        /*
         * Implementations.
         */
        br_rsa_public irsapub;
        /*
         * Implementations.
         */
        br_rsa_public irsapub;
-       br_rsa_pkcs1_vrfy irsavrfy;
-       br_ecdsa_vrfy iecdsa;
 #endif
 #endif
-} br_ssl_client_context;
+};
+
+/**
+ * \brief Get the hash functions and signature algorithms supported by
+ * the server.
+ *
+ * This is a field of bits: for hash function of ID x, bit x is set if
+ * the hash function is supported in RSA signatures, 8+x if it is supported
+ * with ECDSA. This information is conveyed by the server when requesting
+ * a client certificate.
+ *
+ * \param cc   client context.
+ * \return  the server-supported hash functions (for signatures).
+ */
+static inline uint16_t
+br_ssl_client_get_server_hashes(const br_ssl_client_context *cc)
+{
+       return cc->hashes;
+}
+
+/**
+ * \brief Get the server key curve.
+ *
+ * This function returns the ID for the curve used by the server's public
+ * key. This is set when the server's certificate chain is processed;
+ * this value is 0 if the server's key is not an EC key.
+ *
+ * \return  the server's public key curve ID, or 0.
+ */
+static inline int
+br_ssl_client_get_server_curve(const br_ssl_client_context *cc)
+{
+       return cc->server_curve;
+}
 
 /*
  * Each br_ssl_client_init_xxx() function sets the list of supported
 
 /*
  * Each br_ssl_client_init_xxx() function sets the list of supported
@@ -1668,48 +2134,34 @@ void br_ssl_client_init_full(br_ssl_client_context *cc,
 void br_ssl_client_zero(br_ssl_client_context *cc);
 
 /**
 void br_ssl_client_zero(br_ssl_client_context *cc);
 
 /**
- * \brief Set the RSA public-key operations implementation.
+ * \brief Set an externally provided client certificate handler context.
  *
  *
- * This will be used to encrypt the pre-master secret with the server's
- * RSA public key (RSA-encryption cipher suites only).
+ * The handler's methods are invoked when the server requests a client
+ * certificate.
  *
  *
- * \param cc        client context.
- * \param irsapub   RSA public-key encryption implementation.
+ * \param cc     client context.
+ * \param pctx   certificate handler context (pointer to its vtable field).
  */
 static inline void
  */
 static inline void
-br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
+br_ssl_client_set_client_certificate(br_ssl_client_context *cc,
+       const br_ssl_client_certificate_class **pctx)
 {
 {
-       cc->irsapub = irsapub;
+       cc->client_auth_vtable = pctx;
 }
 
 /**
 }
 
 /**
- * \brief Set the RSA signature verification implementation.
- *
- * This will be used to verify the server's signature on its
- * ServerKeyExchange message (ECDHE_RSA cipher suites only).
- *
- * \param cc         client context.
- * \param irsavrfy   RSA signature verification implementation.
- */
-static inline void
-br_ssl_client_set_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
-{
-       cc->irsavrfy = irsavrfy;
-}
-
-/*
- * \brief Set the ECDSA implementation (signature verification).
+ * \brief Set the RSA public-key operations implementation.
  *
  *
- * The ECDSA implementation will use the EC core implementation configured
- * in the engine context.
+ * This will be used to encrypt the pre-master secret with the server's
+ * RSA public key (RSA-encryption cipher suites only).
  *
  *
- * \param cc       client context.
- * \param iecdsa   ECDSA verification implementation.
+ * \param cc        client context.
+ * \param irsapub   RSA public-key encryption implementation.
  */
 static inline void
  */
 static inline void
-br_ssl_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)
+br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
 {
 {
-       cc->iecdsa = iecdsa;
+       cc->irsapub = irsapub;
 }
 
 /**
 }
 
 /**
@@ -1783,6 +2235,73 @@ br_ssl_client_forget_session(br_ssl_client_context *cc)
        cc->eng.session.session_id_len = 0;
 }
 
        cc->eng.session.session_id_len = 0;
 }
 
+/**
+ * \brief Set client certificate chain and key (single RSA case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an RSA public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * \param cc          SSL client context.
+ * \param chain       client certificate chain (SSL order: EE comes first).
+ * \param chain_len   client chain length (number of certificates).
+ * \param sk          client private key.
+ * \param irsasign    RSA signature implementation (PKCS#1 v1.5).
+ */
+void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);
+
+/*
+ * \brief Set the client certificate chain and key (single EC case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an EC public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`
+ * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value
+ * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA
+ * signature implementation must be provided; otherwise, the `iecdsa`
+ * parameter may be 0.
+ *
+ * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or
+ * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA
+ * that issued (signed) the client certificate. That value is used with
+ * full static ECDH: support of the certificate by the server depends
+ * on how the certificate was signed. (Note: when using TLS 1.2, this
+ * parameter is ignored; but its value matters for TLS 1.0 and 1.1.)
+ *
+ * \param cc                     server context.
+ * \param chain                  server certificate chain to send.
+ * \param chain_len              chain length (number of certificates).
+ * \param sk                     server private key (EC).
+ * \param allowed_usages         allowed private key usages.
+ * \param cert_issuer_key_type   issuing CA's key type.
+ * \param iec                    EC core implementation.
+ * \param iecdsa                 ECDSA signature implementation ("asn1" format).
+ */
+void br_ssl_client_set_single_ec(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_ec_private_key *sk, unsigned allowed_usages,
+       unsigned cert_issuer_key_type,
+       const br_ec_impl *iec, br_ecdsa_sign iecdsa);
+
 /**
  * \brief Type for a "translated cipher suite", as an array of two
  * 16-bit integers.
 /**
  * \brief Type for a "translated cipher suite", as an array of two
  * 16-bit integers.
@@ -1906,6 +2425,7 @@ typedef struct {
         * \brief Certificate chain length (number of certificates).
         */
        size_t chain_len;
         * \brief Certificate chain length (number of certificates).
         */
        size_t chain_len;
+
 } br_ssl_server_choices;
 
 /**
 } br_ssl_server_choices;
 
 /**
@@ -2244,10 +2764,6 @@ struct br_ssl_server_context_ {
         * Context for chain handler.
         */
        const br_ssl_server_policy_class **policy_vtable;
         * Context for chain handler.
         */
        const br_ssl_server_policy_class **policy_vtable;
-       const br_x509_certificate *chain;
-       size_t chain_len;
-       const unsigned char *cert_cur;
-       size_t cert_len;
        unsigned char sign_hash_id;
 
        /*
        unsigned char sign_hash_id;
 
        /*
@@ -2266,6 +2782,25 @@ struct br_ssl_server_context_ {
        unsigned char ecdhe_key[70];
        size_t ecdhe_key_len;
 
        unsigned char ecdhe_key[70];
        size_t ecdhe_key_len;
 
+       /*
+        * Trust anchor names for client authentication. "ta_names" and
+        * "tas" cannot be both non-NULL.
+        */
+       const br_x500_name *ta_names;
+       const br_x509_trust_anchor *tas;
+       size_t num_tas;
+       size_t cur_dn_index;
+       const unsigned char *cur_dn;
+       size_t cur_dn_len;
+
+       /*
+        * Buffer for the hash value computed over all handshake messages
+        * prior to CertificateVerify, and identifier for the hash function.
+        */
+       unsigned char hash_CV[64];
+       size_t hash_CV_len;
+       int hash_CV_id;
+
        /*
         * Server-specific implementations.
         * (none for now)
        /*
         * Server-specific implementations.
         * (none for now)
@@ -2539,7 +3074,7 @@ void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
        const br_rsa_private_key *sk, unsigned allowed_usages,
        br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
 
        const br_rsa_private_key *sk, unsigned allowed_usages,
        br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
 
-/*
+/**
  * \brief Set the server certificate chain and key (single EC case).
  *
  * This function uses a policy context included in the server context.
  * \brief Set the server certificate chain and key (single EC case).
  *
  * This function uses a policy context included in the server context.
@@ -2569,6 +3104,61 @@ void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
        unsigned cert_issuer_key_type,
        const br_ec_impl *iec, br_ecdsa_sign iecdsa);
 
        unsigned cert_issuer_key_type,
        const br_ec_impl *iec, br_ecdsa_sign iecdsa);
 
+/**
+ * \brief Activate client certificate authentication.
+ *
+ * The trust anchor encoded X.500 names (DN) to send to the client are
+ * provided. A client certificate will be requested and validated through
+ * the X.509 validator configured in the SSL engine. If `num` is 0, then
+ * client certificate authentication is disabled.
+ *
+ * If the client does not send a certificate, or on validation failure,
+ * the handshake aborts. Unauthenticated clients can be tolerated by
+ * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag.
+ *
+ * The provided array is linked in, not copied, so that pointer must
+ * remain valid as long as anchor names may be used.
+ *
+ * \param cc         server context.
+ * \param ta_names   encoded trust anchor names.
+ * \param num        number of encoded trust anchor names.
+ */
+static inline void
+br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc,
+       const br_x500_name *ta_names, size_t num)
+{
+       cc->ta_names = ta_names;
+       cc->tas = NULL;
+       cc->num_tas = num;
+}
+
+/**
+ * \brief Activate client certificate authentication.
+ *
+ * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the
+ * trust anchor names are provided not as an array of stand-alone names
+ * (`br_x500_name` structures), but as an array of trust anchors
+ * (`br_x509_trust_anchor` structures). The server engine itself will
+ * only use the `dn` field of each trust anchor. This is meant to allow
+ * defining a single array of trust anchors, to be used here and in the
+ * X.509 validation engine itself.
+ *
+ * The provided array is linked in, not copied, so that pointer must
+ * remain valid as long as anchor names may be used.
+ *
+ * \param cc    server context.
+ * \param tas   trust anchors (only names are used).
+ * \param num   number of trust anchors.
+ */
+static inline void
+br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc,
+       const br_x509_trust_anchor *tas, size_t num)
+{
+       cc->ta_names = NULL;
+       cc->tas = tas;
+       cc->num_tas = num;
+}
+
 /**
  * \brief Configure the cache for session parameters.
  *
 /**
  * \brief Configure the cache for session parameters.
  *
index 84e73dc..c73b5b3 100644 (file)
  *     include some limited processing for case-insensitive matching and
  *     whitespace normalisation).
  *
  *     include some limited processing for case-insensitive matching and
  *     whitespace normalisation).
  *
- *   - When doing validation, a target public key type is provided. That
- *     type is the combination of a key algorithm (RSA or EC) and an
- *     intended key usage (key exchange or signature); in the context
- *     of a SSL/TLS client validating a server's certificate, the algorithm
- *     and usage are obtained from the cipher suite (e.g. ECDHE_RSA means
- *     that an RSA key for signatures is expected).
+ *   - Successful validation produces a public key type but also a set
+ *     of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ *     The caller is responsible for checking that the key type and
+ *     usages are compatible with the expected values (e.g. with the
+ *     selected cipher suite, when the client validates the server's
+ *     certificate).
  *
  * **Important caveats:**
  *
  *
  * **Important caveats:**
  *
@@ -233,14 +233,24 @@ typedef struct {
        } key;
 } br_x509_pkey;
 
        } key;
 } br_x509_pkey;
 
+/**
+ * \brief Distinguished Name (X.500) structure.
+ *
+ * The DN is DER-encoded.
+ */
+typedef struct {
+       /** \brief Encoded DN data. */
+       unsigned char *data;
+       /** \brief Encoded DN length (in bytes). */
+       size_t len;
+} br_x500_name;
+
 /**
  * \brief Trust anchor structure.
  */
 typedef struct {
        /** \brief Encoded DN (X.500 name). */
 /**
  * \brief Trust anchor structure.
  */
 typedef struct {
        /** \brief Encoded DN (X.500 name). */
-       unsigned char *dn;
-       /** \brief Encoded DN length (in bytes). */
-       size_t dn_len;
+       br_x500_name dn;
        /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */
        unsigned flags;
        /** \brief Anchor public key. */
        /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */
        unsigned flags;
        /** \brief Anchor public key. */
@@ -364,22 +374,16 @@ struct br_x509_class_ {
         * This method shall set the vtable (first field) of the context
         * structure.
         *
         * This method shall set the vtable (first field) of the context
         * structure.
         *
-        * The `expected_key_type` is a combination of the algorithm type
-        * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) and the key usage
-        * (`BR_KEYTYPE_KEYX` or `BR_KEYTYPE_SIGN`).
-        *
         * The `server_name`, if not `NULL`, will be considered as a
         * fully qualified domain name, to be matched against the `dNSName`
         * elements of the end-entity certificate's SAN extension (if there
         * is no SAN, then the Common Name from the subjectDN will be used).
         * If `server_name` is `NULL` then no such matching is performed.
         *
         * The `server_name`, if not `NULL`, will be considered as a
         * fully qualified domain name, to be matched against the `dNSName`
         * elements of the end-entity certificate's SAN extension (if there
         * is no SAN, then the Common Name from the subjectDN will be used).
         * If `server_name` is `NULL` then no such matching is performed.
         *
-        * \param ctx                 validation context.
-        * \param expected_key_type   expected key type (algorithm and usage).
-        * \param server_name         server name to match (or `NULL`).
+        * \param ctx           validation context.
+        * \param server_name   server name to match (or `NULL`).
         */
        void (*start_chain)(const br_x509_class **ctx,
         */
        void (*start_chain)(const br_x509_class **ctx,
-               unsigned expected_key_type,
                const char *server_name);
 
        /**
                const char *server_name);
 
        /**
@@ -446,10 +450,17 @@ struct br_x509_class_ {
         * a decoded public key even if the chain did not end on a
         * trusted anchor.
         *
         * a decoded public key even if the chain did not end on a
         * trusted anchor.
         *
+        * If validation succeeded and `usage` is not `NULL`, then
+        * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`
+        * and/or `BR_KEYTYPE_KEYX` that specifies the validated key
+        * usage types. It is the caller's responsibility to check
+        * that value against the intended use of the public key.
+        *
         * \param ctx   validation context.
         * \return  the end-entity public key, or `NULL`.
         */
         * \param ctx   validation context.
         * \return  the end-entity public key, or `NULL`.
         */
-       const br_x509_pkey *(*get_pkey)(const br_x509_class *const *ctx);
+       const br_x509_pkey *(*get_pkey)(
+               const br_x509_class *const *ctx, unsigned *usages);
 };
 
 /**
 };
 
 /**
@@ -466,6 +477,7 @@ typedef struct {
        const br_x509_class *vtable;
 #ifndef BR_DOXYGEN_IGNORE
        br_x509_pkey pkey;
        const br_x509_class *vtable;
 #ifndef BR_DOXYGEN_IGNORE
        br_x509_pkey pkey;
+       unsigned usages;
 #endif
 } br_x509_knownkey_context;
 
 #endif
 } br_x509_knownkey_context;
 
@@ -477,26 +489,34 @@ extern const br_x509_class br_x509_knownkey_vtable;
 /**
  * \brief Initialize a "known key" X.509 engine with a known RSA public key.
  *
 /**
  * \brief Initialize a "known key" X.509 engine with a known RSA public key.
  *
+ * The `usages` parameter indicates the allowed key usages for that key
+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ *
  * The provided pointers are linked in, not copied, so they must remain
  * valid while the public key may be in usage.
  *
  * The provided pointers are linked in, not copied, so they must remain
  * valid while the public key may be in usage.
  *
- * \param ctx   context to initialise.
- * \param pk    known public key.
+ * \param ctx      context to initialise.
+ * \param pk       known public key.
+ * \param usages   allowed key usages.
  */
 void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
  */
 void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
-       const br_rsa_public_key *pk);
+       const br_rsa_public_key *pk, unsigned usages);
 
 /**
  * \brief Initialize a "known key" X.509 engine with a known EC public key.
  *
 
 /**
  * \brief Initialize a "known key" X.509 engine with a known EC public key.
  *
+ * The `usages` parameter indicates the allowed key usages for that key
+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ *
  * The provided pointers are linked in, not copied, so they must remain
  * valid while the public key may be in usage.
  *
  * The provided pointers are linked in, not copied, so they must remain
  * valid while the public key may be in usage.
  *
- * \param ctx   context to initialise.
- * \param pk    known public key.
+ * \param ctx      context to initialise.
+ * \param pk       known public key.
+ * \param usages   allowed key usages.
  */
 void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
  */
 void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
-       const br_ec_public_key *pk);
+       const br_ec_public_key *pk, unsigned usages);
 
 #ifndef BR_DOXYGEN_IGNORE
 /*
 
 #ifndef BR_DOXYGEN_IGNORE
 /*
@@ -560,8 +580,8 @@ typedef struct {
        /* Server name to match with the SAN / CN of the EE certificate. */
        const char *server_name;
 
        /* Server name to match with the SAN / CN of the EE certificate. */
        const char *server_name;
 
-       /* Expected EE key type and usage. */
-       unsigned char expected_key_type;
+       /* Validated key usages. */
+       unsigned char key_usages;
 
        /* Explicitly set date and time. */
        uint32_t days, seconds;
 
        /* Explicitly set date and time. */
        uint32_t days, seconds;
diff --git a/src/ssl/ssl_ccert_single_ec.c b/src/ssl/ssl_ccert_single_ec.c
new file mode 100644 (file)
index 0000000..1df19a9
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+static void
+cc_none0(const br_ssl_client_certificate_class **pctx)
+{
+       (void)pctx;
+}
+
+static void
+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+       (void)pctx;
+       (void)len;
+}
+
+static void
+cc_none2(const br_ssl_client_certificate_class **pctx,
+       const unsigned char *data, size_t len)
+{
+       (void)pctx;
+       (void)data;
+       (void)len;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+       const br_ssl_client_context *cc, uint32_t auth_types,
+       br_ssl_client_certificate *choices)
+{
+       br_ssl_client_certificate_ec_context *zc;
+       int x;
+       int scurve;
+
+       zc = (br_ssl_client_certificate_ec_context *)pctx;
+       scurve = br_ssl_client_get_server_curve(cc);
+
+       if ((zc->allowed_usages & BR_KEYTYPE_KEYX) != 0
+               && scurve == zc->sk->curve)
+       {
+               int x;
+
+               x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17;
+               if (((auth_types >> x) & 1) != 0) {
+                       choices->auth_type = BR_AUTH_ECDH;
+                       choices->hash_id = -1;
+                       choices->chain = zc->chain;
+                       choices->chain_len = zc->chain_len;
+               }
+       }
+
+       /*
+        * For ECDSA authentication, we must choose an appropriate
+        * hash function.
+        */
+       x = br_ssl_choose_hash((unsigned)(auth_types >> 8));
+       if (x == 0 || (zc->allowed_usages & BR_KEYTYPE_SIGN) == 0) {
+               memset(choices, 0, sizeof *choices);
+               return;
+       }
+       choices->auth_type = BR_AUTH_ECDSA;
+       choices->hash_id = x;
+       choices->chain = zc->chain;
+       choices->chain_len = zc->chain_len;
+}
+
+static uint32_t
+cc_do_keyx(const br_ssl_client_certificate_class **pctx,
+       unsigned char *data, size_t len)
+{
+       br_ssl_client_certificate_ec_context *zc;
+
+       zc = (br_ssl_client_certificate_ec_context *)pctx;
+       return zc->iec->mul(data, len, zc->sk->x, zc->sk->xlen, zc->sk->curve);
+}
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+       int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+       br_ssl_client_certificate_ec_context *zc;
+       unsigned char hv[64];
+       const br_hash_class *hc;
+
+       zc = (br_ssl_client_certificate_ec_context *)pctx;
+       memcpy(hv, data, hv_len);
+       hc = br_multihash_getimpl(zc->mhash, hash_id);
+       if (hc == NULL) {
+               return 0;
+       }
+       if (len < 139) {
+               return 0;
+       }
+       return zc->iecdsa(zc->iec, hc, hv, zc->sk, data);
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+       sizeof(br_ssl_client_certificate_ec_context),
+       cc_none0, /* start_name_list */
+       cc_none1, /* start_name */
+       cc_none2, /* append_name */
+       cc_none0, /* end_name */
+       cc_none0, /* end_name_list */
+       cc_choose,
+       cc_do_keyx,
+       cc_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_client_set_single_ec(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_ec_private_key *sk, unsigned allowed_usages,
+       unsigned cert_issuer_key_type,
+       const br_ec_impl *iec, br_ecdsa_sign iecdsa)
+{
+       cc->client_auth.single_ec.vtable = &ccert_vtable;
+       cc->client_auth.single_ec.chain = chain;
+       cc->client_auth.single_ec.chain_len = chain_len;
+       cc->client_auth.single_ec.sk = sk;
+       cc->client_auth.single_ec.allowed_usages = allowed_usages;
+       cc->client_auth.single_ec.issuer_key_type = cert_issuer_key_type;
+       cc->client_auth.single_ec.mhash = &cc->eng.mhash;
+       cc->client_auth.single_ec.iec = iec;
+       cc->client_auth.single_ec.iecdsa = iecdsa;
+       cc->client_auth_vtable = &cc->client_auth.single_ec.vtable;
+}
diff --git a/src/ssl/ssl_ccert_single_rsa.c b/src/ssl/ssl_ccert_single_rsa.c
new file mode 100644 (file)
index 0000000..690df20
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+static void
+cc_none0(const br_ssl_client_certificate_class **pctx)
+{
+       (void)pctx;
+}
+
+static void
+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+       (void)pctx;
+       (void)len;
+}
+
+static void
+cc_none2(const br_ssl_client_certificate_class **pctx,
+       const unsigned char *data, size_t len)
+{
+       (void)pctx;
+       (void)data;
+       (void)len;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+       const br_ssl_client_context *cc, uint32_t auth_types,
+       br_ssl_client_certificate *choices)
+{
+       br_ssl_client_certificate_rsa_context *zc;
+       int x;
+
+       (void)cc;
+       zc = (br_ssl_client_certificate_rsa_context *)pctx;
+       x = br_ssl_choose_hash((unsigned)auth_types);
+       if (x == 0 && (auth_types & 1) == 0) {
+               memset(choices, 0, sizeof *choices);
+       }
+       choices->auth_type = BR_AUTH_RSA;
+       choices->hash_id = x;
+       choices->chain = zc->chain;
+       choices->chain_len = zc->chain_len;
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+       HASH_OID_SHA1,
+       HASH_OID_SHA224,
+       HASH_OID_SHA256,
+       HASH_OID_SHA384,
+       HASH_OID_SHA512
+};
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+       int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+       br_ssl_client_certificate_rsa_context *zc;
+       unsigned char hv[64];
+       const unsigned char *hash_oid;
+       size_t sig_len;
+
+       zc = (br_ssl_client_certificate_rsa_context *)pctx;
+       memcpy(hv, data, hv_len);
+       if (hash_id == 0) {
+               hash_oid = NULL;
+       } else if (hash_id >= 2 && hash_id <= 6) {
+               hash_oid = HASH_OID[hash_id - 2];
+       } else {
+               return 0;
+       }
+       sig_len = (zc->sk->n_bitlen + 7) >> 3;
+       if (len < sig_len) {
+               return 0;
+       }
+       return zc->irsasign(hash_oid, hv, hv_len, zc->sk, data) ? sig_len : 0;
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+       sizeof(br_ssl_client_certificate_rsa_context),
+       cc_none0, /* start_name_list */
+       cc_none1, /* start_name */
+       cc_none2, /* append_name */
+       cc_none0, /* end_name */
+       cc_none0, /* end_name_list */
+       cc_choose,
+       0,
+       cc_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign)
+{
+       cc->client_auth.single_rsa.vtable = &ccert_vtable;
+       cc->client_auth.single_rsa.chain = chain;
+       cc->client_auth.single_rsa.chain_len = chain_len;
+       cc->client_auth.single_rsa.sk = sk;
+       cc->client_auth.single_rsa.irsasign = irsasign;
+       cc->client_auth_vtable = &cc->client_auth.single_rsa.vtable;
+}
index ad1f0cc..64f9327 100644 (file)
@@ -123,9 +123,9 @@ br_ssl_client_init_full(br_ssl_client_context *cc,
        br_ssl_engine_set_suites(&cc->eng, suites,
                (sizeof suites) / (sizeof suites[0]));
        br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
        br_ssl_engine_set_suites(&cc->eng, suites,
                (sizeof suites) / (sizeof suites[0]));
        br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
-       br_ssl_client_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy);
+       br_ssl_engine_set_rsavrfy(&cc->eng, &br_rsa_i31_pkcs1_vrfy);
        br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31);
        br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31);
-       br_ssl_client_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1);
+       br_ssl_engine_set_ecdsa(&cc->eng, &br_ecdsa_i31_vrfy_asn1);
        br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
        br_x509_minimal_set_ecdsa(xc,
                &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
        br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
        br_x509_minimal_set_ecdsa(xc,
                &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
index a347cc6..e7334de 100644 (file)
@@ -110,7 +110,7 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
        size_t nlen, u;
 
        xc = ctx->eng.x509ctx;
        size_t nlen, u;
 
        xc = ctx->eng.x509ctx;
-       pk = (*xc)->get_pkey(xc);
+       pk = (*xc)->get_pkey(xc, NULL);
 
        /*
         * Compute actual RSA key length, in case there are leading zeros.
 
        /*
         * Compute actual RSA key length, in case there are leading zeros.
@@ -200,9 +200,11 @@ static const unsigned char *HASH_OID[] = {
 
 /*
  * Check the RSA signature on the ServerKeyExchange message.
 
 /*
  * Check the RSA signature on the ServerKeyExchange message.
+ *
  *   hash      hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
  *   use_rsa   non-zero for RSA signature, zero for ECDSA
  *   sig_len   signature length (in bytes); signature value is in the pad
  *   hash      hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
  *   use_rsa   non-zero for RSA signature, zero for ECDSA
  *   sig_len   signature length (in bytes); signature value is in the pad
+ *
  * Returned value is 0 on success, or an error code.
  */
 static int
  * Returned value is 0 on success, or an error code.
  */
 static int
@@ -216,7 +218,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,
        size_t hv_len;
 
        xc = ctx->eng.x509ctx;
        size_t hv_len;
 
        xc = ctx->eng.x509ctx;
-       pk = (*xc)->get_pkey(xc);
+       pk = (*xc)->get_pkey(xc, NULL);
        br_multihash_zero(&mhc);
        br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
        br_multihash_init(&mhc);
        br_multihash_zero(&mhc);
        br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
        br_multihash_init(&mhc);
@@ -253,14 +255,14 @@ verify_SKE_sig(br_ssl_client_context *ctx,
                } else {
                        hash_oid = NULL;
                }
                } else {
                        hash_oid = NULL;
                }
-               if (!ctx->irsavrfy(ctx->eng.pad, sig_len,
+               if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
                        hash_oid, hv_len, &pk->key.rsa, tmp)
                        || memcmp(tmp, hv, hv_len) != 0)
                {
                        return BR_ERR_BAD_SIGNATURE;
                }
        } else {
                        hash_oid, hv_len, &pk->key.rsa, tmp)
                        || memcmp(tmp, hv, hv_len) != 0)
                {
                        return BR_ERR_BAD_SIGNATURE;
                }
        } else {
-               if (!ctx->iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
+               if (!ctx->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
                        ctx->eng.pad, sig_len))
                {
                        return BR_ERR_BAD_SIGNATURE;
                        ctx->eng.pad, sig_len))
                {
                        return BR_ERR_BAD_SIGNATURE;
@@ -270,7 +272,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,
 }
 
 /*
 }
 
 /*
- * Perform client-size ECDH (or ECDHE). The point that should be sent to
+ * Perform client-side ECDH (or ECDHE). The point that should be sent to
  * the server is written in the pad; returned value is either the point
  * length (in bytes), or -x on error, with 'x' being an error code.
  *
  * the server is written in the pad; returned value is either the point
  * length (in bytes), or -x on error, with 'x' being an error code.
  *
@@ -296,7 +298,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
                const br_x509_pkey *pk;
 
                xc = ctx->eng.x509ctx;
                const br_x509_pkey *pk;
 
                xc = ctx->eng.x509ctx;
-               pk = (*xc)->get_pkey(xc);
+               pk = (*xc)->get_pkey(xc, NULL);
                curve = pk->key.ec.curve;
                point_src = pk->key.ec.q;
                point_len = pk->key.ec.qlen;
                curve = pk->key.ec.curve;
                point_src = pk->key.ec.q;
                point_len = pk->key.ec.qlen;
@@ -347,6 +349,73 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
        return (int)glen;
 }
 
        return (int)glen;
 }
 
+/*
+ * Perform full static ECDH. This occurs only in the context of client
+ * authentication with certificates: the server uses an EC public key,
+ * the cipher suite is of type ECDH (not ECDHE), the server requested a
+ * client certificate and accepts static ECDH, the client has a
+ * certificate with an EC public key in the same curve, and accepts
+ * static ECDH as well.
+ *
+ * Returned value is 0 on success, -1 on error.
+ */
+static int
+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
+{
+       unsigned char point[133];
+       size_t point_len;
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       point_len = pk->key.ec.qlen;
+       if (point_len > sizeof point) {
+               return -1;
+       }
+       memcpy(point, pk->key.ec.q, point_len);
+       if (!(*ctx->client_auth_vtable)->do_keyx(
+               ctx->client_auth_vtable, point, point_len))
+       {
+               return -1;
+       }
+       br_ssl_engine_compute_master(&ctx->eng,
+               prf_id, point + 1, point_len >> 1);
+       return 0;
+}
+
+/*
+ * Compute the client-side signature. This is invoked only when a
+ * signature-based client authentication was selected. The computed
+ * signature is in the pad; its length (in bytes) is returned. On
+ * error, 0 is returned.
+ */
+static size_t
+make_client_sign(br_ssl_client_context *ctx)
+{
+       size_t hv_len;
+
+       /*
+        * Compute hash of handshake messages so far. This "cannot" fail
+        * because the list of supported hash functions provided to the
+        * client certificate handler was trimmed to include only the
+        * hash functions that the multi-hasher supports.
+        */
+       if (ctx->hash_id) {
+               hv_len = br_multihash_out(&ctx->eng.mhash,
+                       ctx->hash_id, ctx->eng.pad);
+       } else {
+               br_multihash_out(&ctx->eng.mhash,
+                       br_md5_ID, ctx->eng.pad);
+               br_multihash_out(&ctx->eng.mhash,
+                       br_sha1_ID, ctx->eng.pad + 16);
+               hv_len = 36;
+       }
+       return (*ctx->client_auth_vtable)->do_sign(
+               ctx->client_auth_vtable, ctx->hash_id, hv_len,
+               ctx->eng.pad, sizeof ctx->eng.pad);
+}
+
 
 
 static const uint8_t t0_datablock[] = {
 
 
 static const uint8_t t0_datablock[] = {
@@ -366,10 +435,10 @@ static const uint8_t t0_datablock[] = {
 };
 
 static const uint8_t t0_codeblock[] = {
 };
 
 static const uint8_t t0_codeblock[] = {
-       0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x01,
-       0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01, 0x01, 0x08,
+       0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01,
+       0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08,
        0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
        0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
-       0x01, 0x02, 0x09, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01,
+       0x01, 0x02, 0x09, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01,
@@ -387,9 +456,11 @@ static const uint8_t t0_codeblock[] = {
        T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01,
+       T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
        T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
+       0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00,
        0x01,
        T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)),
        0x00, 0x00, 0x01,
        0x01,
        T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)),
        0x00, 0x00, 0x01,
@@ -400,6 +471,8 @@ static const uint8_t t0_codeblock[] = {
        T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00,
        T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00,
+       0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00,
+       0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
        0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
        0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00,
@@ -426,218 +499,259 @@ static const uint8_t t0_codeblock[] = {
        T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
        T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
-       0x00, 0x00, 0x09, 0x1B, 0x42, 0x06, 0x02, 0x52, 0x1C, 0x00, 0x00, 0x06,
-       0x08, 0x1E, 0x0D, 0x05, 0x02, 0x5B, 0x1C, 0x04, 0x01, 0x2D, 0x00, 0x00,
-       0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x7D, 0x1B, 0x48, 0x34, 0x81, 0x01,
-       0x1B, 0x05, 0x04, 0x4A, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0D, 0x06, 0x03,
-       0x81, 0x01, 0x00, 0x48, 0x04, 0x69, 0x00, 0x06, 0x02, 0x52, 0x1C, 0x00,
-       0x00, 0x1B, 0x6E, 0x34, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x34, 0x61, 0x1E,
-       0x81, 0x0F, 0x15, 0x6A, 0x01, 0x0C, 0x23, 0x00, 0x00, 0x1B, 0x16, 0x01,
-       0x08, 0x0B, 0x34, 0x46, 0x16, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00,
-       0x60, 0x2E, 0x1D, 0x13, 0x28, 0x06, 0x08, 0x02, 0x00, 0x81, 0x2E, 0x03,
-       0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x26, 0x02, 0x00, 0x1B, 0x13, 0x11,
-       0x06, 0x02, 0x59, 0x1C, 0x81, 0x2E, 0x04, 0x75, 0x01, 0x01, 0x00, 0x60,
-       0x2E, 0x01, 0x16, 0x6C, 0x2E, 0x26, 0x81, 0x32, 0x1D, 0x81, 0x16, 0x06,
-       0x0B, 0x01, 0x7F, 0x81, 0x12, 0x01, 0x7F, 0x81, 0x31, 0x04, 0x80, 0x42,
-       0x81, 0x13, 0x61, 0x1E, 0x81, 0x05, 0x01, T0_INT1(BR_KEYTYPE_SIGN),
-       0x11, 0x06, 0x02, 0x81, 0x17, 0x81, 0x1A, 0x1B, 0x01, 0x0D, 0x0D, 0x06,
-       0x09, 0x1A, 0x81, 0x19, 0x81, 0x1A, 0x01, 0x7F, 0x04, 0x02, 0x01, 0x00,
-       0x03, 0x00, 0x01, 0x0E, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x06, 0x02, 0x51,
-       0x1C, 0x25, 0x06, 0x02, 0x5C, 0x1C, 0x02, 0x00, 0x06, 0x02, 0x81, 0x38,
-       0x81, 0x33, 0x01, 0x7F, 0x81, 0x31, 0x01, 0x7F, 0x81, 0x12, 0x01, 0x01,
-       0x60, 0x2E, 0x01, 0x17, 0x6C, 0x2E, 0x00, 0x00, 0x2A, 0x2A, 0x00, 0x00,
-       0x7E, 0x01, 0x0C, 0x10, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,
-       T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, 0x01, 0x01,
-       0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,
+       0x00, 0x00, 0x09, 0x25, 0x50, 0x06, 0x02, 0x60, 0x26, 0x00, 0x00, 0x06,
+       0x08, 0x2A, 0x0E, 0x05, 0x02, 0x69, 0x26, 0x04, 0x01, 0x3A, 0x00, 0x00,
+       0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x81, 0x0F, 0x25, 0x56, 0x41, 0x81,
+       0x13, 0x25, 0x05, 0x04, 0x58, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06,
+       0x03, 0x81, 0x13, 0x00, 0x56, 0x04, 0x69, 0x00, 0x06, 0x02, 0x60, 0x26,
+       0x00, 0x00, 0x25, 0x81, 0x00, 0x41, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x41,
+       0x71, 0x2A, 0x81, 0x21, 0x1C, 0x7C, 0x01, 0x0C, 0x2F, 0x00, 0x00, 0x25,
+       0x1E, 0x01, 0x08, 0x0B, 0x41, 0x54, 0x1E, 0x08, 0x00, 0x01, 0x03, 0x00,
+       0x01, 0x00, 0x6F, 0x3B, 0x27, 0x1A, 0x34, 0x06, 0x08, 0x02, 0x00, 0x81,
+       0x43, 0x03, 0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x3A, 0x02, 0x00, 0x25,
+       0x1A, 0x17, 0x06, 0x02, 0x67, 0x26, 0x81, 0x43, 0x04, 0x75, 0x01, 0x01,
+       0x00, 0x6F, 0x3B, 0x01, 0x16, 0x7E, 0x3B, 0x32, 0x81, 0x49, 0x27, 0x81,
+       0x29, 0x06, 0x0B, 0x01, 0x7F, 0x81, 0x24, 0x01, 0x7F, 0x81, 0x46, 0x04,
+       0x80, 0x62, 0x81, 0x26, 0x71, 0x2A, 0x81, 0x17, 0x01,
+       T0_INT1(BR_KEYTYPE_SIGN), 0x17, 0x06, 0x02, 0x81, 0x2A, 0x81, 0x2D,
+       0x25, 0x01, 0x0D, 0x0E, 0x06, 0x09, 0x24, 0x81, 0x2C, 0x81, 0x2D, 0x01,
+       0x7F, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01, 0x0E, 0x0E, 0x05, 0x02,
+       0x6A, 0x26, 0x06, 0x02, 0x5F, 0x26, 0x31, 0x06, 0x02, 0x6A, 0x26, 0x02,
+       0x00, 0x06, 0x22, 0x81, 0x47, 0x78, 0x2C, 0x01, 0x81, 0x7F, 0x0E, 0x06,
+       0x10, 0x24, 0x01, 0x10, 0x81, 0x52, 0x01, 0x00, 0x81, 0x51, 0x71, 0x2A,
+       0x81, 0x21, 0x23, 0x04, 0x06, 0x81, 0x4A, 0x06, 0x02, 0x81, 0x48, 0x04,
+       0x02, 0x81, 0x4A, 0x01, 0x7F, 0x81, 0x46, 0x01, 0x7F, 0x81, 0x24, 0x01,
+       0x01, 0x6F, 0x3B, 0x01, 0x17, 0x7E, 0x3B, 0x00, 0x00, 0x36, 0x36, 0x00,
+       0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x01, 0x00, 0x36, 0x0E, 0x06, 0x05,
+       0x24, 0x01, T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30,
+       0x01, 0x01, 0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,
        T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02,
        T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02,
-       0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,
+       0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03,
-       0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,
+       0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04,
-       0x2A, 0x0D, 0x06, 0x05, 0x1A, 0x01,
+       0x36, 0x0E, 0x06, 0x05, 0x24, 0x01,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00,
        T0_INT1(BR_KEYTYPE_EC  | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00,
-       0x34, 0x1A, 0x00, 0x00, 0x68, 0x20, 0x01, 0x0E, 0x0D, 0x06, 0x04, 0x01,
-       0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x30, 0x06, 0x04, 0x01, 0x06,
-       0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x6D, 0x20, 0x1B, 0x06, 0x08, 0x01,
-       0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x1A, 0x01, 0x05, 0x00, 0x01,
-       0x31, 0x03, 0x00, 0x1A, 0x01, 0x00, 0x33, 0x06, 0x03, 0x02, 0x00, 0x08,
-       0x32, 0x06, 0x03, 0x02, 0x00, 0x08, 0x1B, 0x06, 0x06, 0x01, 0x01, 0x0B,
-       0x01, 0x06, 0x08, 0x00, 0x00, 0x6F, 0x2F, 0x1B, 0x06, 0x03, 0x01, 0x09,
-       0x08, 0x00, 0x01, 0x30, 0x1B, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x1B,
-       0x06, 0x0E, 0x1B, 0x01, 0x01, 0x11, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01,
-       0x01, 0x10, 0x04, 0x6F, 0x1A, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06,
-       0x08, 0x00, 0x00, 0x67, 0x1F, 0x34, 0x10, 0x01, 0x01, 0x11, 0x27, 0x00,
-       0x00, 0x81, 0x03, 0x81, 0x2D, 0x1B, 0x01, 0x07, 0x11, 0x01, 0x00, 0x2A,
-       0x0D, 0x06, 0x0A, 0x1A, 0x01, 0x10, 0x11, 0x06, 0x02, 0x81, 0x03, 0x04,
-       0x32, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x29, 0x1A, 0x1A, 0x01, 0x00, 0x60,
-       0x2E, 0x81, 0x15, 0x6D, 0x20, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x81, 0x0C,
-       0x29, 0x06, 0x11, 0x1D, 0x13, 0x28, 0x06, 0x05, 0x81, 0x2D, 0x1A, 0x04,
-       0x77, 0x01, 0x80, 0x64, 0x81, 0x26, 0x04, 0x02, 0x81, 0x03, 0x04, 0x03,
-       0x5C, 0x1C, 0x1A, 0x04, 0xFF, 0x35, 0x01, 0x1B, 0x03, 0x00, 0x09, 0x1B,
-       0x42, 0x06, 0x02, 0x52, 0x1C, 0x02, 0x00, 0x00, 0x00, 0x7E, 0x01, 0x0F,
-       0x11, 0x00, 0x00, 0x5F, 0x20, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x10, 0x1A,
-       0x1B, 0x01, 0x01, 0x0C, 0x06, 0x03, 0x1A, 0x01, 0x02, 0x5F, 0x2E, 0x01,
-       0x00, 0x04, 0x22, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x15, 0x1A, 0x01, 0x00,
-       0x5F, 0x2E, 0x1B, 0x01, 0x80, 0x64, 0x0D, 0x06, 0x05, 0x01, 0x82, 0x00,
-       0x08, 0x1C, 0x44, 0x00, 0x04, 0x07, 0x1A, 0x01, 0x82, 0x00, 0x08, 0x1C,
-       0x1A, 0x00, 0x00, 0x01, 0x00, 0x21, 0x06, 0x06, 0x2C, 0x81, 0x10, 0x29,
-       0x04, 0x77, 0x1B, 0x06, 0x04, 0x01, 0x01, 0x73, 0x2E, 0x00, 0x00, 0x21,
-       0x06, 0x0B, 0x6B, 0x20, 0x01, 0x14, 0x0C, 0x06, 0x02, 0x5C, 0x1C, 0x04,
-       0x12, 0x81, 0x2D, 0x01, 0x07, 0x11, 0x1B, 0x01, 0x02, 0x0C, 0x06, 0x06,
-       0x06, 0x02, 0x5C, 0x1C, 0x04, 0x6F, 0x1A, 0x81, 0x23, 0x01, 0x01, 0x0C,
-       0x25, 0x29, 0x06, 0x02, 0x4B, 0x1C, 0x1B, 0x01, 0x01, 0x81, 0x29, 0x28,
-       0x81, 0x14, 0x00, 0x01, 0x81, 0x1A, 0x01, 0x0B, 0x0D, 0x05, 0x02, 0x5C,
-       0x1C, 0x61, 0x1E, 0x81, 0x05, 0x41, 0x81, 0x21, 0x81, 0x0E, 0x1B, 0x06,
-       0x26, 0x81, 0x21, 0x81, 0x0E, 0x1B, 0x40, 0x1B, 0x06, 0x19, 0x1B, 0x01,
-       0x82, 0x00, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x1B, 0x03,
-       0x00, 0x6A, 0x02, 0x00, 0x81, 0x18, 0x02, 0x00, 0x3D, 0x04, 0x64, 0x7F,
-       0x3E, 0x04, 0x57, 0x7F, 0x7F, 0x3F, 0x1B, 0x06, 0x01, 0x1C, 0x1A, 0x00,
-       0x00, 0x81, 0x00, 0x81, 0x1A, 0x01, 0x14, 0x0C, 0x06, 0x02, 0x5C, 0x1C,
-       0x6A, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x18, 0x7F, 0x6A, 0x1B, 0x01,
-       0x0C, 0x08, 0x01, 0x0C, 0x22, 0x05, 0x02, 0x4E, 0x1C, 0x00, 0x00, 0x81,
-       0x1B, 0x06, 0x02, 0x5C, 0x1C, 0x06, 0x02, 0x50, 0x1C, 0x00, 0x09, 0x81,
-       0x1A, 0x01, 0x02, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x81, 0x20, 0x03, 0x00,
-       0x02, 0x00, 0x79, 0x1E, 0x0A, 0x02, 0x00, 0x78, 0x1E, 0x0E, 0x29, 0x06,
-       0x02, 0x5D, 0x1C, 0x02, 0x00, 0x77, 0x1E, 0x0C, 0x06, 0x02, 0x55, 0x1C,
-       0x02, 0x00, 0x7A, 0x2D, 0x70, 0x01, 0x20, 0x81, 0x18, 0x01, 0x00, 0x03,
-       0x01, 0x81, 0x22, 0x03, 0x02, 0x02, 0x02, 0x01, 0x20, 0x0E, 0x06, 0x02,
-       0x5A, 0x1C, 0x6A, 0x02, 0x02, 0x81, 0x18, 0x02, 0x02, 0x72, 0x20, 0x0D,
-       0x02, 0x02, 0x01, 0x00, 0x0E, 0x11, 0x06, 0x0B, 0x71, 0x6A, 0x02, 0x02,
-       0x22, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x01, 0x71, 0x6A, 0x02, 0x02, 0x23,
-       0x02, 0x02, 0x72, 0x2E, 0x02, 0x00, 0x76, 0x02, 0x01, 0x7C, 0x81, 0x20,
-       0x1B, 0x81, 0x24, 0x42, 0x06, 0x02, 0x4C, 0x1C, 0x61, 0x02, 0x01, 0x7C,
-       0x81, 0x22, 0x06, 0x02, 0x4D, 0x1C, 0x1B, 0x06, 0x81, 0x3D, 0x81, 0x20,
-       0x81, 0x0E, 0x81, 0x0A, 0x03, 0x03, 0x81, 0x08, 0x03, 0x04, 0x81, 0x06,
-       0x03, 0x05, 0x81, 0x09, 0x03, 0x06, 0x81, 0x0B, 0x03, 0x07, 0x81, 0x07,
-       0x03, 0x08, 0x1B, 0x06, 0x81, 0x0B, 0x81, 0x20, 0x01, 0x00, 0x2A, 0x0D,
-       0x06, 0x10, 0x1A, 0x02, 0x03, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03,
-       0x03, 0x81, 0x1F, 0x04, 0x80, 0x70, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x10,
-       0x1A, 0x02, 0x05, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x05, 0x81,
-       0x1D, 0x04, 0x80, 0x5A, 0x01, 0x83, 0xFE, 0x01, 0x2A, 0x0D, 0x06, 0x10,
-       0x1A, 0x02, 0x04, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x04, 0x81,
-       0x1E, 0x04, 0x80, 0x42, 0x01, 0x0D, 0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02,
-       0x06, 0x05, 0x02, 0x56, 0x1C, 0x01, 0x00, 0x03, 0x06, 0x81, 0x1C, 0x04,
-       0x2D, 0x01, 0x0A, 0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02, 0x07, 0x05, 0x02,
-       0x56, 0x1C, 0x01, 0x00, 0x03, 0x07, 0x81, 0x1C, 0x04, 0x18, 0x01, 0x0B,
-       0x2A, 0x0D, 0x06, 0x0F, 0x1A, 0x02, 0x08, 0x05, 0x02, 0x56, 0x1C, 0x01,
-       0x00, 0x03, 0x08, 0x81, 0x1C, 0x04, 0x03, 0x56, 0x1C, 0x1A, 0x04, 0xFE,
-       0x71, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0E, 0x06, 0x02,
-       0x53, 0x1C, 0x01, 0x01, 0x6D, 0x2E, 0x7F, 0x7F, 0x02, 0x01, 0x00, 0x04,
-       0x81, 0x1A, 0x01, 0x0C, 0x0D, 0x05, 0x02, 0x5C, 0x1C, 0x81, 0x22, 0x01,
-       0x03, 0x0D, 0x05, 0x02, 0x57, 0x1C, 0x81, 0x20, 0x1B, 0x64, 0x2E, 0x1B,
-       0x01, 0x20, 0x0F, 0x06, 0x02, 0x57, 0x1C, 0x30, 0x34, 0x10, 0x01, 0x01,
-       0x11, 0x05, 0x02, 0x57, 0x1C, 0x81, 0x22, 0x1B, 0x01, 0x81, 0x05, 0x0E,
-       0x06, 0x02, 0x57, 0x1C, 0x1B, 0x66, 0x2E, 0x65, 0x34, 0x81, 0x18, 0x76,
-       0x1E, 0x01, 0x86, 0x03, 0x0F, 0x03, 0x00, 0x61, 0x1E, 0x81, 0x2B, 0x03,
-       0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x00, 0x06, 0x23, 0x81, 0x22, 0x1B,
-       0x1B, 0x01, 0x02, 0x0A, 0x34, 0x01, 0x06, 0x0E, 0x29, 0x06, 0x02, 0x57,
-       0x1C, 0x03, 0x02, 0x81, 0x22, 0x02, 0x01, 0x01, 0x01, 0x0B, 0x01, 0x03,
-       0x08, 0x0D, 0x05, 0x02, 0x57, 0x1C, 0x04, 0x08, 0x02, 0x01, 0x06, 0x04,
-       0x01, 0x00, 0x03, 0x02, 0x81, 0x20, 0x1B, 0x03, 0x03, 0x1B, 0x01, 0x84,
-       0x00, 0x0E, 0x06, 0x02, 0x58, 0x1C, 0x6A, 0x34, 0x81, 0x18, 0x02, 0x02,
-       0x02, 0x01, 0x02, 0x03, 0x3A, 0x1B, 0x06, 0x01, 0x1C, 0x1A, 0x7F, 0x00,
-       0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x7B, 0x02, 0x01, 0x02, 0x00,
-       0x2B, 0x1B, 0x01, 0x00, 0x0D, 0x06, 0x02, 0x4A, 0x00, 0x81, 0x2F, 0x04,
-       0x73, 0x00, 0x1B, 0x06, 0x05, 0x81, 0x22, 0x1A, 0x04, 0x78, 0x1A, 0x00,
-       0x00, 0x81, 0x1B, 0x1B, 0x44, 0x06, 0x07, 0x1A, 0x06, 0x02, 0x50, 0x1C,
-       0x04, 0x73, 0x00, 0x00, 0x81, 0x23, 0x01, 0x03, 0x81, 0x21, 0x34, 0x1A,
-       0x34, 0x00, 0x00, 0x81, 0x20, 0x81, 0x27, 0x00, 0x00, 0x81, 0x20, 0x01,
-       0x01, 0x0D, 0x05, 0x02, 0x4F, 0x1C, 0x81, 0x22, 0x01, 0x08, 0x08, 0x68,
-       0x20, 0x0D, 0x05, 0x02, 0x4F, 0x1C, 0x00, 0x00, 0x81, 0x20, 0x6D, 0x20,
-       0x05, 0x16, 0x01, 0x01, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x81, 0x22, 0x01,
-       0x00, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x01, 0x02, 0x6D, 0x2E, 0x04, 0x1E,
-       0x01, 0x19, 0x0D, 0x05, 0x02, 0x53, 0x1C, 0x81, 0x22, 0x01, 0x18, 0x0D,
-       0x05, 0x02, 0x53, 0x1C, 0x6A, 0x01, 0x18, 0x81, 0x18, 0x6E, 0x6A, 0x01,
-       0x18, 0x22, 0x05, 0x02, 0x53, 0x1C, 0x00, 0x00, 0x81, 0x20, 0x06, 0x02,
-       0x54, 0x1C, 0x00, 0x00, 0x01, 0x02, 0x7B, 0x81, 0x23, 0x01, 0x08, 0x0B,
-       0x81, 0x23, 0x08, 0x00, 0x00, 0x01, 0x03, 0x7B, 0x81, 0x23, 0x01, 0x08,
-       0x0B, 0x81, 0x23, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x23, 0x08, 0x00, 0x00,
-       0x01, 0x01, 0x7B, 0x81, 0x23, 0x00, 0x00, 0x2C, 0x1B, 0x42, 0x05, 0x01,
-       0x00, 0x1A, 0x81, 0x2F, 0x04, 0x75, 0x02, 0x03, 0x00, 0x75, 0x20, 0x03,
-       0x01, 0x01, 0x00, 0x1B, 0x02, 0x01, 0x0A, 0x06, 0x10, 0x1B, 0x01, 0x01,
-       0x0B, 0x74, 0x08, 0x1E, 0x02, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x46, 0x04,
-       0x6A, 0x1A, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x15, 0x6C, 0x2E, 0x34, 0x3C,
-       0x1A, 0x3C, 0x1A, 0x1D, 0x00, 0x00, 0x01, 0x01, 0x34, 0x81, 0x25, 0x00,
-       0x00, 0x34, 0x2A, 0x7B, 0x34, 0x1B, 0x06, 0x06, 0x81, 0x23, 0x1A, 0x47,
-       0x04, 0x77, 0x1A, 0x00, 0x00, 0x1B, 0x01, 0x81, 0xAC, 0x00, 0x0D, 0x06,
-       0x04, 0x1A, 0x01, 0x7F, 0x00, 0x7E, 0x43, 0x00, 0x02, 0x03, 0x00, 0x61,
-       0x1E, 0x7E, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x11, 0x02, 0x01, 0x01,
-       0x04, 0x10, 0x01, 0x0F, 0x11, 0x02, 0x01, 0x01, 0x08, 0x10, 0x01, 0x0F,
-       0x11, 0x01, 0x00, 0x2A, 0x0D, 0x06, 0x10, 0x1A, 0x01, 0x00, 0x01, 0x18,
-       0x02, 0x00, 0x06, 0x03, 0x37, 0x04, 0x01, 0x38, 0x04, 0x80, 0x56, 0x01,
-       0x01, 0x2A, 0x0D, 0x06, 0x10, 0x1A, 0x01, 0x01, 0x01, 0x10, 0x02, 0x00,
-       0x06, 0x03, 0x37, 0x04, 0x01, 0x38, 0x04, 0x80, 0x40, 0x01, 0x02, 0x2A,
-       0x0D, 0x06, 0x0F, 0x1A, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03,
-       0x37, 0x04, 0x01, 0x38, 0x04, 0x2B, 0x01, 0x03, 0x2A, 0x0D, 0x06, 0x0E,
-       0x1A, 0x1A, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x35, 0x04, 0x01, 0x36,
-       0x04, 0x17, 0x01, 0x04, 0x2A, 0x0D, 0x06, 0x0E, 0x1A, 0x1A, 0x01, 0x20,
-       0x02, 0x00, 0x06, 0x03, 0x35, 0x04, 0x01, 0x36, 0x04, 0x03, 0x52, 0x1C,
-       0x1A, 0x00, 0x00, 0x7E, 0x01, 0x0C, 0x10, 0x1B, 0x45, 0x34, 0x01, 0x03,
-       0x0A, 0x11, 0x00, 0x00, 0x7E, 0x01, 0x0C, 0x10, 0x01, 0x01, 0x0D, 0x00,
-       0x00, 0x7E, 0x01, 0x0C, 0x10, 0x44, 0x00, 0x00, 0x14, 0x01, 0x00, 0x5E,
-       0x20, 0x1B, 0x06, 0x20, 0x01, 0x01, 0x2A, 0x0D, 0x06, 0x07, 0x1A, 0x01,
-       0x00, 0x81, 0x02, 0x04, 0x11, 0x01, 0x02, 0x2A, 0x0D, 0x06, 0x0A, 0x1A,
-       0x60, 0x20, 0x06, 0x03, 0x01, 0x10, 0x29, 0x04, 0x01, 0x1A, 0x04, 0x01,
-       0x1A, 0x63, 0x20, 0x05, 0x35, 0x21, 0x06, 0x32, 0x6B, 0x20, 0x01, 0x14,
-       0x2A, 0x0D, 0x06, 0x06, 0x1A, 0x01, 0x02, 0x29, 0x04, 0x24, 0x01, 0x15,
-       0x2A, 0x0D, 0x06, 0x0B, 0x1A, 0x81, 0x11, 0x06, 0x04, 0x01, 0x7F, 0x81,
-       0x02, 0x04, 0x13, 0x01, 0x16, 0x2A, 0x0D, 0x06, 0x06, 0x1A, 0x01, 0x01,
-       0x29, 0x04, 0x07, 0x1A, 0x01, 0x04, 0x29, 0x01, 0x00, 0x1A, 0x13, 0x06,
-       0x03, 0x01, 0x08, 0x29, 0x00, 0x00, 0x14, 0x1B, 0x05, 0x10, 0x21, 0x06,
-       0x0D, 0x6B, 0x20, 0x01, 0x15, 0x0D, 0x06, 0x05, 0x1A, 0x81, 0x11, 0x04,
-       0x01, 0x17, 0x00, 0x00, 0x81, 0x2D, 0x01, 0x07, 0x11, 0x01, 0x01, 0x0E,
-       0x06, 0x02, 0x5C, 0x1C, 0x00, 0x01, 0x03, 0x00, 0x1D, 0x13, 0x06, 0x05,
-       0x02, 0x00, 0x6C, 0x2E, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x73, 0x00, 0x01,
-       0x14, 0x81, 0x30, 0x01, 0x01, 0x81, 0x3C, 0x1D, 0x1B, 0x01, 0x00, 0x81,
-       0x29, 0x01, 0x16, 0x81, 0x30, 0x81, 0x34, 0x1D, 0x00, 0x02, 0x81, 0x08,
-       0x81, 0x0A, 0x08, 0x81, 0x06, 0x08, 0x81, 0x09, 0x08, 0x81, 0x0B, 0x08,
-       0x81, 0x07, 0x08, 0x03, 0x00, 0x01, 0x01, 0x81, 0x3C, 0x01, 0x27, 0x72,
-       0x20, 0x08, 0x75, 0x20, 0x01, 0x01, 0x0B, 0x08, 0x02, 0x00, 0x06, 0x04,
-       0x48, 0x02, 0x00, 0x08, 0x69, 0x1E, 0x2A, 0x09, 0x1B, 0x45, 0x06, 0x24,
-       0x02, 0x00, 0x05, 0x04, 0x34, 0x48, 0x34, 0x49, 0x01, 0x04, 0x09, 0x1B,
-       0x42, 0x06, 0x03, 0x1A, 0x01, 0x00, 0x1B, 0x01, 0x04, 0x08, 0x02, 0x00,
-       0x08, 0x03, 0x00, 0x34, 0x01, 0x04, 0x08, 0x2A, 0x08, 0x34, 0x04, 0x03,
-       0x1A, 0x01, 0x7F, 0x03, 0x01, 0x81, 0x3B, 0x78, 0x1E, 0x81, 0x3A, 0x62,
-       0x01, 0x04, 0x12, 0x62, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x24, 0x62, 0x01,
-       0x20, 0x81, 0x35, 0x71, 0x72, 0x20, 0x81, 0x37, 0x75, 0x20, 0x1B, 0x01,
-       0x01, 0x0B, 0x81, 0x3A, 0x74, 0x34, 0x1B, 0x06, 0x11, 0x47, 0x2A, 0x1E,
-       0x1B, 0x81, 0x28, 0x05, 0x02, 0x4C, 0x1C, 0x81, 0x3A, 0x34, 0x48, 0x34,
-       0x04, 0x6C, 0x4A, 0x01, 0x01, 0x81, 0x3C, 0x01, 0x00, 0x81, 0x3C, 0x02,
-       0x00, 0x06, 0x81, 0x47, 0x02, 0x00, 0x81, 0x3A, 0x81, 0x08, 0x06, 0x12,
-       0x01, 0x83, 0xFE, 0x01, 0x81, 0x3A, 0x6E, 0x81, 0x08, 0x01, 0x04, 0x09,
-       0x1B, 0x81, 0x3A, 0x47, 0x81, 0x37, 0x81, 0x0A, 0x06, 0x1C, 0x01, 0x00,
-       0x81, 0x3A, 0x6F, 0x81, 0x0A, 0x01, 0x04, 0x09, 0x1B, 0x81, 0x3A, 0x01,
-       0x02, 0x09, 0x1B, 0x81, 0x3A, 0x01, 0x00, 0x81, 0x3C, 0x01, 0x03, 0x09,
-       0x81, 0x36, 0x81, 0x06, 0x06, 0x0F, 0x01, 0x01, 0x81, 0x3A, 0x01, 0x01,
-       0x81, 0x3A, 0x68, 0x20, 0x01, 0x08, 0x09, 0x81, 0x3C, 0x81, 0x09, 0x06,
-       0x1F, 0x01, 0x0D, 0x81, 0x3A, 0x81, 0x09, 0x01, 0x04, 0x09, 0x1B, 0x81,
-       0x3A, 0x01, 0x02, 0x09, 0x81, 0x3A, 0x32, 0x06, 0x04, 0x01, 0x03, 0x81,
-       0x39, 0x33, 0x06, 0x04, 0x01, 0x01, 0x81, 0x39, 0x81, 0x0B, 0x1B, 0x06,
-       0x27, 0x01, 0x0A, 0x81, 0x3A, 0x01, 0x04, 0x09, 0x1B, 0x81, 0x3A, 0x49,
-       0x81, 0x3A, 0x30, 0x01, 0x00, 0x1B, 0x01, 0x20, 0x0A, 0x06, 0x0E, 0x81,
-       0x04, 0x10, 0x01, 0x01, 0x11, 0x06, 0x03, 0x1B, 0x81, 0x3A, 0x46, 0x04,
-       0x6C, 0x4A, 0x04, 0x01, 0x1A, 0x81, 0x07, 0x06, 0x0D, 0x01, 0x0B, 0x81,
-       0x3A, 0x01, 0x02, 0x81, 0x3A, 0x01, 0x82, 0x00, 0x81, 0x3A, 0x02, 0x01,
-       0x42, 0x05, 0x14, 0x01, 0x15, 0x81, 0x3A, 0x02, 0x01, 0x1B, 0x81, 0x3A,
-       0x1B, 0x06, 0x07, 0x47, 0x01, 0x00, 0x81, 0x3C, 0x04, 0x76, 0x1A, 0x00,
-       0x00, 0x01, 0x10, 0x81, 0x3C, 0x61, 0x1E, 0x1B, 0x81, 0x2C, 0x06, 0x10,
-       0x81, 0x0F, 0x19, 0x1B, 0x48, 0x81, 0x3B, 0x1B, 0x81, 0x3A, 0x6A, 0x34,
-       0x81, 0x35, 0x04, 0x12, 0x1B, 0x81, 0x2A, 0x34, 0x81, 0x0F, 0x18, 0x1B,
-       0x46, 0x81, 0x3B, 0x1B, 0x81, 0x3C, 0x6A, 0x34, 0x81, 0x35, 0x00, 0x00,
-       0x81, 0x00, 0x01, 0x14, 0x81, 0x3C, 0x01, 0x0C, 0x81, 0x3B, 0x6A, 0x01,
-       0x0C, 0x81, 0x35, 0x00, 0x00, 0x3B, 0x1B, 0x01, 0x00, 0x0D, 0x06, 0x02,
-       0x4A, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x72, 0x00, 0x1B, 0x81, 0x3A, 0x81,
-       0x35, 0x00, 0x00, 0x1B, 0x81, 0x3C, 0x81, 0x35, 0x00, 0x00, 0x01, 0x0B,
-       0x81, 0x3C, 0x01, 0x03, 0x81, 0x3B, 0x01, 0x00, 0x81, 0x3B, 0x00, 0x01,
-       0x03, 0x00, 0x31, 0x1A, 0x1B, 0x01, 0x10, 0x11, 0x06, 0x08, 0x01, 0x04,
-       0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01, 0x08, 0x11, 0x06, 0x08,
-       0x01, 0x03, 0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01, 0x20, 0x11,
-       0x06, 0x08, 0x01, 0x05, 0x81, 0x3C, 0x02, 0x00, 0x81, 0x3C, 0x1B, 0x01,
-       0x80, 0x40, 0x11, 0x06, 0x08, 0x01, 0x06, 0x81, 0x3C, 0x02, 0x00, 0x81,
-       0x3C, 0x01, 0x04, 0x11, 0x06, 0x08, 0x01, 0x02, 0x81, 0x3C, 0x02, 0x00,
-       0x81, 0x3C, 0x00, 0x00, 0x1B, 0x01, 0x08, 0x39, 0x81, 0x3C, 0x81, 0x3C,
-       0x00, 0x00, 0x1B, 0x01, 0x10, 0x39, 0x81, 0x3C, 0x81, 0x3A, 0x00, 0x00,
-       0x1B, 0x3C, 0x06, 0x02, 0x1A, 0x00, 0x81, 0x2D, 0x1A, 0x04, 0x75
+       0x41, 0x24, 0x00, 0x00, 0x7A, 0x2C, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01,
+       0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x3D, 0x06, 0x04, 0x01, 0x06,
+       0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x7F, 0x2C, 0x25, 0x06, 0x08, 0x01,
+       0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x24, 0x01, 0x05, 0x00, 0x01,
+       0x3E, 0x03, 0x00, 0x24, 0x01, 0x00, 0x40, 0x06, 0x03, 0x02, 0x00, 0x08,
+       0x3F, 0x06, 0x03, 0x02, 0x00, 0x08, 0x25, 0x06, 0x06, 0x01, 0x01, 0x0B,
+       0x01, 0x06, 0x08, 0x00, 0x00, 0x81, 0x01, 0x3C, 0x25, 0x06, 0x03, 0x01,
+       0x09, 0x08, 0x00, 0x01, 0x3D, 0x25, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00,
+       0x25, 0x06, 0x0E, 0x25, 0x01, 0x01, 0x17, 0x02, 0x00, 0x08, 0x03, 0x00,
+       0x01, 0x01, 0x11, 0x04, 0x6F, 0x24, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01,
+       0x06, 0x08, 0x00, 0x00, 0x77, 0x2B, 0x41, 0x11, 0x01, 0x01, 0x17, 0x33,
+       0x00, 0x00, 0x81, 0x15, 0x81, 0x42, 0x25, 0x01, 0x07, 0x17, 0x01, 0x00,
+       0x36, 0x0E, 0x06, 0x0A, 0x24, 0x01, 0x10, 0x17, 0x06, 0x02, 0x81, 0x15,
+       0x04, 0x32, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x29, 0x24, 0x24, 0x01, 0x00,
+       0x6F, 0x3B, 0x81, 0x28, 0x7F, 0x2C, 0x01, 0x01, 0x0E, 0x01, 0x01, 0x81,
+       0x1E, 0x35, 0x06, 0x11, 0x27, 0x1A, 0x34, 0x06, 0x05, 0x81, 0x42, 0x24,
+       0x04, 0x77, 0x01, 0x80, 0x64, 0x81, 0x3A, 0x04, 0x02, 0x81, 0x15, 0x04,
+       0x03, 0x6A, 0x26, 0x24, 0x04, 0xFF, 0x35, 0x01, 0x25, 0x03, 0x00, 0x09,
+       0x25, 0x50, 0x06, 0x02, 0x60, 0x26, 0x02, 0x00, 0x00, 0x00, 0x81, 0x10,
+       0x01, 0x0F, 0x17, 0x00, 0x00, 0x6E, 0x2C, 0x01, 0x00, 0x36, 0x0E, 0x06,
+       0x10, 0x24, 0x25, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x24, 0x01, 0x02, 0x6E,
+       0x3B, 0x01, 0x00, 0x04, 0x22, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x15, 0x24,
+       0x01, 0x00, 0x6E, 0x3B, 0x25, 0x01, 0x80, 0x64, 0x0E, 0x06, 0x05, 0x01,
+       0x82, 0x00, 0x08, 0x26, 0x52, 0x00, 0x04, 0x07, 0x24, 0x01, 0x82, 0x00,
+       0x08, 0x26, 0x24, 0x00, 0x00, 0x01, 0x00, 0x2D, 0x06, 0x06, 0x38, 0x81,
+       0x22, 0x35, 0x04, 0x77, 0x25, 0x06, 0x05, 0x01, 0x01, 0x81, 0x05, 0x3B,
+       0x00, 0x00, 0x2D, 0x06, 0x0B, 0x7D, 0x2C, 0x01, 0x14, 0x0D, 0x06, 0x02,
+       0x6A, 0x26, 0x04, 0x12, 0x81, 0x42, 0x01, 0x07, 0x17, 0x25, 0x01, 0x02,
+       0x0D, 0x06, 0x06, 0x06, 0x02, 0x6A, 0x26, 0x04, 0x6F, 0x24, 0x81, 0x37,
+       0x01, 0x01, 0x0D, 0x31, 0x35, 0x06, 0x02, 0x59, 0x26, 0x25, 0x01, 0x01,
+       0x81, 0x3D, 0x34, 0x81, 0x27, 0x00, 0x01, 0x81, 0x2D, 0x01, 0x0B, 0x0E,
+       0x05, 0x02, 0x6A, 0x26, 0x25, 0x01, 0x03, 0x0E, 0x06, 0x09, 0x81, 0x35,
+       0x06, 0x02, 0x60, 0x26, 0x41, 0x24, 0x00, 0x41, 0x4F, 0x81, 0x35, 0x81,
+       0x20, 0x25, 0x06, 0x27, 0x81, 0x35, 0x81, 0x20, 0x25, 0x4E, 0x25, 0x06,
+       0x19, 0x25, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04,
+       0x01, 0x25, 0x03, 0x00, 0x7C, 0x02, 0x00, 0x81, 0x2B, 0x02, 0x00, 0x4B,
+       0x04, 0x64, 0x81, 0x11, 0x4C, 0x04, 0x56, 0x81, 0x11, 0x81, 0x11, 0x4D,
+       0x25, 0x06, 0x02, 0x33, 0x00, 0x24, 0x29, 0x00, 0x00, 0x71, 0x2A, 0x81,
+       0x17, 0x01, 0x7F, 0x81, 0x25, 0x25, 0x50, 0x06, 0x02, 0x33, 0x26, 0x25,
+       0x05, 0x02, 0x6A, 0x26, 0x36, 0x17, 0x0D, 0x06, 0x02, 0x6C, 0x26, 0x39,
+       0x00, 0x00, 0x81, 0x12, 0x81, 0x2D, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x6A,
+       0x26, 0x7C, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x2B, 0x81, 0x11, 0x7C,
+       0x25, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x2E, 0x05, 0x02, 0x5C, 0x26, 0x00,
+       0x00, 0x81, 0x2E, 0x06, 0x02, 0x6A, 0x26, 0x06, 0x02, 0x5E, 0x26, 0x00,
+       0x09, 0x81, 0x2D, 0x01, 0x02, 0x0E, 0x05, 0x02, 0x6A, 0x26, 0x81, 0x34,
+       0x03, 0x00, 0x02, 0x00, 0x81, 0x0B, 0x2A, 0x0A, 0x02, 0x00, 0x81, 0x0A,
+       0x2A, 0x0F, 0x35, 0x06, 0x02, 0x6B, 0x26, 0x02, 0x00, 0x81, 0x09, 0x2A,
+       0x0D, 0x06, 0x02, 0x63, 0x26, 0x02, 0x00, 0x81, 0x0C, 0x3A, 0x81, 0x02,
+       0x01, 0x20, 0x81, 0x2B, 0x01, 0x00, 0x03, 0x01, 0x81, 0x36, 0x03, 0x02,
+       0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, 0x02, 0x68, 0x26, 0x7C, 0x02, 0x02,
+       0x81, 0x2B, 0x02, 0x02, 0x81, 0x04, 0x2C, 0x0E, 0x02, 0x02, 0x01, 0x00,
+       0x0F, 0x17, 0x06, 0x0C, 0x81, 0x03, 0x7C, 0x02, 0x02, 0x2E, 0x06, 0x04,
+       0x01, 0x7F, 0x03, 0x01, 0x81, 0x03, 0x7C, 0x02, 0x02, 0x2F, 0x02, 0x02,
+       0x81, 0x04, 0x3B, 0x02, 0x00, 0x81, 0x08, 0x02, 0x01, 0x81, 0x0E, 0x81,
+       0x34, 0x25, 0x81, 0x38, 0x50, 0x06, 0x02, 0x5A, 0x26, 0x71, 0x02, 0x01,
+       0x81, 0x0E, 0x81, 0x36, 0x06, 0x02, 0x5B, 0x26, 0x25, 0x06, 0x81, 0x3E,
+       0x81, 0x34, 0x81, 0x20, 0x81, 0x1C, 0x03, 0x03, 0x81, 0x1A, 0x03, 0x04,
+       0x81, 0x18, 0x03, 0x05, 0x81, 0x1B, 0x03, 0x06, 0x81, 0x1D, 0x03, 0x07,
+       0x81, 0x19, 0x03, 0x08, 0x25, 0x06, 0x81, 0x0B, 0x81, 0x34, 0x01, 0x00,
+       0x36, 0x0E, 0x06, 0x10, 0x24, 0x02, 0x03, 0x05, 0x02, 0x64, 0x26, 0x01,
+       0x00, 0x03, 0x03, 0x81, 0x33, 0x04, 0x80, 0x70, 0x01, 0x01, 0x36, 0x0E,
+       0x06, 0x10, 0x24, 0x02, 0x05, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03,
+       0x05, 0x81, 0x31, 0x04, 0x80, 0x5A, 0x01, 0x83, 0xFE, 0x01, 0x36, 0x0E,
+       0x06, 0x10, 0x24, 0x02, 0x04, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03,
+       0x04, 0x81, 0x32, 0x04, 0x80, 0x42, 0x01, 0x0D, 0x36, 0x0E, 0x06, 0x0F,
+       0x24, 0x02, 0x06, 0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03, 0x06, 0x81,
+       0x2F, 0x04, 0x2D, 0x01, 0x0A, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x02, 0x07,
+       0x05, 0x02, 0x64, 0x26, 0x01, 0x00, 0x03, 0x07, 0x81, 0x2F, 0x04, 0x18,
+       0x01, 0x0B, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x02, 0x08, 0x05, 0x02, 0x64,
+       0x26, 0x01, 0x00, 0x03, 0x08, 0x81, 0x2F, 0x04, 0x03, 0x64, 0x26, 0x24,
+       0x04, 0xFE, 0x71, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F,
+       0x06, 0x02, 0x61, 0x26, 0x01, 0x01, 0x7F, 0x3B, 0x81, 0x11, 0x81, 0x11,
+       0x02, 0x01, 0x00, 0x04, 0x81, 0x2D, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x6A,
+       0x26, 0x81, 0x36, 0x01, 0x03, 0x0E, 0x05, 0x02, 0x65, 0x26, 0x81, 0x34,
+       0x25, 0x74, 0x3B, 0x25, 0x01, 0x20, 0x10, 0x06, 0x02, 0x65, 0x26, 0x3D,
+       0x41, 0x11, 0x01, 0x01, 0x17, 0x05, 0x02, 0x65, 0x26, 0x81, 0x36, 0x25,
+       0x01, 0x81, 0x05, 0x0F, 0x06, 0x02, 0x65, 0x26, 0x25, 0x76, 0x3B, 0x75,
+       0x41, 0x81, 0x2B, 0x81, 0x08, 0x2A, 0x01, 0x86, 0x03, 0x10, 0x03, 0x00,
+       0x71, 0x2A, 0x81, 0x40, 0x03, 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x00,
+       0x06, 0x23, 0x81, 0x36, 0x25, 0x25, 0x01, 0x02, 0x0A, 0x41, 0x01, 0x06,
+       0x0F, 0x35, 0x06, 0x02, 0x65, 0x26, 0x03, 0x02, 0x81, 0x36, 0x02, 0x01,
+       0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x65, 0x26, 0x04,
+       0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0x81, 0x34, 0x25,
+       0x03, 0x03, 0x25, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x66, 0x26, 0x7C,
+       0x41, 0x81, 0x2B, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x48, 0x25, 0x06,
+       0x01, 0x26, 0x24, 0x81, 0x11, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02,
+       0x00, 0x81, 0x0D, 0x02, 0x01, 0x02, 0x00, 0x37, 0x25, 0x01, 0x00, 0x0E,
+       0x06, 0x02, 0x58, 0x00, 0x81, 0x44, 0x04, 0x73, 0x02, 0x01, 0x00, 0x03,
+       0x00, 0x81, 0x36, 0x81, 0x20, 0x25, 0x06, 0x80, 0x44, 0x81, 0x36, 0x01,
+       0x01, 0x36, 0x0E, 0x06, 0x06, 0x24, 0x01, 0x81, 0x7F, 0x04, 0x2E, 0x01,
+       0x80, 0x40, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x83, 0xFE, 0x00, 0x04,
+       0x20, 0x01, 0x80, 0x41, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x84, 0x80,
+       0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x36, 0x0E, 0x06, 0x07, 0x24, 0x01,
+       0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00, 0x41, 0x24, 0x02, 0x00, 0x35,
+       0x03, 0x00, 0x04, 0xFF, 0x38, 0x81, 0x11, 0x71, 0x2A, 0x81, 0x3E, 0x05,
+       0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03, 0x00, 0x81, 0x08,
+       0x2A, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3B, 0x81, 0x30, 0x25, 0x79, 0x3A,
+       0x3E, 0x24, 0x25, 0x01, 0x08, 0x0B, 0x35, 0x01, 0x8C, 0x80, 0x00, 0x35,
+       0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17, 0x06,
+       0x19, 0x25, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80, 0x00,
+       0x35, 0x25, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88, 0x80,
+       0x00, 0x35, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88, 0x01,
+       0x17, 0x03, 0x00, 0x16, 0x81, 0x34, 0x81, 0x20, 0x25, 0x06, 0x27, 0x81,
+       0x34, 0x81, 0x20, 0x25, 0x15, 0x25, 0x06, 0x19, 0x25, 0x01, 0x82, 0x00,
+       0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x25, 0x03, 0x01, 0x7C,
+       0x02, 0x01, 0x81, 0x2B, 0x02, 0x01, 0x12, 0x04, 0x64, 0x81, 0x11, 0x13,
+       0x04, 0x56, 0x81, 0x11, 0x14, 0x81, 0x11, 0x02, 0x00, 0x28, 0x00, 0x00,
+       0x81, 0x2E, 0x25, 0x52, 0x06, 0x07, 0x24, 0x06, 0x02, 0x5E, 0x26, 0x04,
+       0x73, 0x00, 0x00, 0x81, 0x37, 0x01, 0x03, 0x81, 0x35, 0x41, 0x24, 0x41,
+       0x00, 0x00, 0x81, 0x34, 0x81, 0x3B, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00,
+       0x81, 0x34, 0x81, 0x20, 0x25, 0x06, 0x34, 0x81, 0x36, 0x03, 0x01, 0x81,
+       0x36, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01, 0x01, 0x06,
+       0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01, 0x03, 0x0E,
+       0x35, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x55, 0x01,
+       0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x35, 0x03, 0x00, 0x04, 0x49, 0x81,
+       0x11, 0x02, 0x00, 0x00, 0x00, 0x81, 0x34, 0x01, 0x01, 0x0E, 0x05, 0x02,
+       0x5D, 0x26, 0x81, 0x36, 0x01, 0x08, 0x08, 0x7A, 0x2C, 0x0E, 0x05, 0x02,
+       0x5D, 0x26, 0x00, 0x00, 0x81, 0x34, 0x7F, 0x2C, 0x05, 0x16, 0x01, 0x01,
+       0x0E, 0x05, 0x02, 0x61, 0x26, 0x81, 0x36, 0x01, 0x00, 0x0E, 0x05, 0x02,
+       0x61, 0x26, 0x01, 0x02, 0x7F, 0x3B, 0x04, 0x1F, 0x01, 0x19, 0x0E, 0x05,
+       0x02, 0x61, 0x26, 0x81, 0x36, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x61, 0x26,
+       0x7C, 0x01, 0x18, 0x81, 0x2B, 0x81, 0x00, 0x7C, 0x01, 0x18, 0x2E, 0x05,
+       0x02, 0x61, 0x26, 0x00, 0x00, 0x81, 0x34, 0x06, 0x02, 0x62, 0x26, 0x00,
+       0x00, 0x01, 0x02, 0x81, 0x0D, 0x81, 0x37, 0x01, 0x08, 0x0B, 0x81, 0x37,
+       0x08, 0x00, 0x00, 0x01, 0x03, 0x81, 0x0D, 0x81, 0x37, 0x01, 0x08, 0x0B,
+       0x81, 0x37, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x37, 0x08, 0x00, 0x00, 0x01,
+       0x01, 0x81, 0x0D, 0x81, 0x37, 0x00, 0x00, 0x38, 0x25, 0x50, 0x05, 0x01,
+       0x00, 0x24, 0x81, 0x44, 0x04, 0x75, 0x02, 0x03, 0x00, 0x81, 0x07, 0x2C,
+       0x03, 0x01, 0x01, 0x00, 0x25, 0x02, 0x01, 0x0A, 0x06, 0x11, 0x25, 0x01,
+       0x01, 0x0B, 0x81, 0x06, 0x08, 0x2A, 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00,
+       0x54, 0x04, 0x69, 0x24, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x15, 0x7E, 0x3B,
+       0x41, 0x4A, 0x24, 0x4A, 0x24, 0x27, 0x00, 0x00, 0x01, 0x01, 0x41, 0x81,
+       0x39, 0x00, 0x00, 0x41, 0x36, 0x81, 0x0D, 0x41, 0x25, 0x06, 0x06, 0x81,
+       0x37, 0x24, 0x55, 0x04, 0x77, 0x24, 0x00, 0x00, 0x25, 0x01, 0x81, 0xAC,
+       0x00, 0x0E, 0x06, 0x04, 0x24, 0x01, 0x7F, 0x00, 0x81, 0x10, 0x51, 0x00,
+       0x02, 0x03, 0x00, 0x71, 0x2A, 0x81, 0x10, 0x03, 0x01, 0x02, 0x01, 0x01,
+       0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02, 0x01,
+       0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x36, 0x0E, 0x06, 0x10,
+       0x24, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01,
+       0x45, 0x04, 0x80, 0x56, 0x01, 0x01, 0x36, 0x0E, 0x06, 0x10, 0x24, 0x01,
+       0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01, 0x45, 0x04,
+       0x80, 0x40, 0x01, 0x02, 0x36, 0x0E, 0x06, 0x0F, 0x24, 0x01, 0x01, 0x01,
+       0x20, 0x02, 0x00, 0x06, 0x03, 0x44, 0x04, 0x01, 0x45, 0x04, 0x2B, 0x01,
+       0x03, 0x36, 0x0E, 0x06, 0x0E, 0x24, 0x24, 0x01, 0x10, 0x02, 0x00, 0x06,
+       0x03, 0x42, 0x04, 0x01, 0x43, 0x04, 0x17, 0x01, 0x04, 0x36, 0x0E, 0x06,
+       0x0E, 0x24, 0x24, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x42, 0x04, 0x01,
+       0x43, 0x04, 0x03, 0x60, 0x26, 0x24, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C,
+       0x11, 0x01, 0x02, 0x0F, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x25,
+       0x53, 0x41, 0x01, 0x03, 0x0A, 0x17, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C,
+       0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x81, 0x10, 0x01, 0x0C, 0x11, 0x52,
+       0x00, 0x00, 0x1B, 0x01, 0x00, 0x6D, 0x2C, 0x25, 0x06, 0x20, 0x01, 0x01,
+       0x36, 0x0E, 0x06, 0x07, 0x24, 0x01, 0x00, 0x81, 0x14, 0x04, 0x11, 0x01,
+       0x02, 0x36, 0x0E, 0x06, 0x0A, 0x24, 0x6F, 0x2C, 0x06, 0x03, 0x01, 0x10,
+       0x35, 0x04, 0x01, 0x24, 0x04, 0x01, 0x24, 0x73, 0x2C, 0x05, 0x35, 0x2D,
+       0x06, 0x32, 0x7D, 0x2C, 0x01, 0x14, 0x36, 0x0E, 0x06, 0x06, 0x24, 0x01,
+       0x02, 0x35, 0x04, 0x24, 0x01, 0x15, 0x36, 0x0E, 0x06, 0x0B, 0x24, 0x81,
+       0x23, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x14, 0x04, 0x13, 0x01, 0x16, 0x36,
+       0x0E, 0x06, 0x06, 0x24, 0x01, 0x01, 0x35, 0x04, 0x07, 0x24, 0x01, 0x04,
+       0x35, 0x01, 0x00, 0x24, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x35, 0x00, 0x00,
+       0x1B, 0x25, 0x05, 0x10, 0x2D, 0x06, 0x0D, 0x7D, 0x2C, 0x01, 0x15, 0x0E,
+       0x06, 0x05, 0x24, 0x81, 0x23, 0x04, 0x01, 0x1F, 0x00, 0x00, 0x81, 0x42,
+       0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02, 0x6A, 0x26, 0x00, 0x01,
+       0x03, 0x00, 0x27, 0x1A, 0x06, 0x05, 0x02, 0x00, 0x7E, 0x3B, 0x00, 0x81,
+       0x42, 0x24, 0x04, 0x73, 0x00, 0x01, 0x14, 0x81, 0x45, 0x01, 0x01, 0x81,
+       0x52, 0x27, 0x25, 0x01, 0x00, 0x81, 0x3D, 0x01, 0x16, 0x81, 0x45, 0x81,
+       0x4B, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x52, 0x46, 0x25, 0x25, 0x01,
+       0x03, 0x08, 0x81, 0x51, 0x81, 0x51, 0x18, 0x25, 0x50, 0x06, 0x02, 0x24,
+       0x00, 0x81, 0x51, 0x1D, 0x25, 0x06, 0x06, 0x7C, 0x41, 0x81, 0x4C, 0x04,
+       0x76, 0x24, 0x04, 0x6A, 0x00, 0x20, 0x01, 0x0F, 0x81, 0x52, 0x25, 0x81,
+       0x08, 0x2A, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0F, 0x01, 0x04, 0x08, 0x81,
+       0x51, 0x78, 0x2C, 0x81, 0x52, 0x70, 0x2C, 0x81, 0x52, 0x04, 0x03, 0x56,
+       0x81, 0x51, 0x25, 0x81, 0x50, 0x7C, 0x41, 0x81, 0x4C, 0x00, 0x02, 0x81,
+       0x1A, 0x81, 0x1C, 0x08, 0x81, 0x18, 0x08, 0x81, 0x1B, 0x08, 0x81, 0x1D,
+       0x08, 0x81, 0x19, 0x08, 0x03, 0x00, 0x01, 0x01, 0x81, 0x52, 0x01, 0x27,
+       0x81, 0x04, 0x2C, 0x08, 0x81, 0x07, 0x2C, 0x01, 0x01, 0x0B, 0x08, 0x02,
+       0x00, 0x06, 0x04, 0x56, 0x02, 0x00, 0x08, 0x7B, 0x2A, 0x36, 0x09, 0x25,
+       0x53, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x41, 0x56, 0x41, 0x57, 0x01,
+       0x04, 0x09, 0x25, 0x50, 0x06, 0x03, 0x24, 0x01, 0x00, 0x25, 0x01, 0x04,
+       0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x41, 0x01, 0x04, 0x08, 0x36, 0x08,
+       0x41, 0x04, 0x03, 0x24, 0x01, 0x7F, 0x03, 0x01, 0x81, 0x51, 0x81, 0x0A,
+       0x2A, 0x81, 0x50, 0x72, 0x01, 0x04, 0x19, 0x72, 0x01, 0x04, 0x08, 0x01,
+       0x1C, 0x30, 0x72, 0x01, 0x20, 0x81, 0x4C, 0x81, 0x03, 0x81, 0x04, 0x2C,
+       0x81, 0x4E, 0x81, 0x07, 0x2C, 0x25, 0x01, 0x01, 0x0B, 0x81, 0x50, 0x81,
+       0x06, 0x41, 0x25, 0x06, 0x11, 0x55, 0x36, 0x2A, 0x25, 0x81, 0x3C, 0x05,
+       0x02, 0x5A, 0x26, 0x81, 0x50, 0x41, 0x56, 0x41, 0x04, 0x6C, 0x58, 0x01,
+       0x01, 0x81, 0x52, 0x01, 0x00, 0x81, 0x52, 0x02, 0x00, 0x06, 0x81, 0x49,
+       0x02, 0x00, 0x81, 0x50, 0x81, 0x1A, 0x06, 0x13, 0x01, 0x83, 0xFE, 0x01,
+       0x81, 0x50, 0x81, 0x00, 0x81, 0x1A, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50,
+       0x55, 0x81, 0x4E, 0x81, 0x1C, 0x06, 0x1D, 0x01, 0x00, 0x81, 0x50, 0x81,
+       0x01, 0x81, 0x1C, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x01, 0x02, 0x09,
+       0x25, 0x81, 0x50, 0x01, 0x00, 0x81, 0x52, 0x01, 0x03, 0x09, 0x81, 0x4D,
+       0x81, 0x18, 0x06, 0x0F, 0x01, 0x01, 0x81, 0x50, 0x01, 0x01, 0x81, 0x50,
+       0x7A, 0x2C, 0x01, 0x08, 0x09, 0x81, 0x52, 0x81, 0x1B, 0x06, 0x1F, 0x01,
+       0x0D, 0x81, 0x50, 0x81, 0x1B, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x01,
+       0x02, 0x09, 0x81, 0x50, 0x3F, 0x06, 0x04, 0x01, 0x03, 0x81, 0x4F, 0x40,
+       0x06, 0x04, 0x01, 0x01, 0x81, 0x4F, 0x81, 0x1D, 0x25, 0x06, 0x27, 0x01,
+       0x0A, 0x81, 0x50, 0x01, 0x04, 0x09, 0x25, 0x81, 0x50, 0x57, 0x81, 0x50,
+       0x3D, 0x01, 0x00, 0x25, 0x01, 0x20, 0x0A, 0x06, 0x0E, 0x81, 0x16, 0x11,
+       0x01, 0x01, 0x17, 0x06, 0x03, 0x25, 0x81, 0x50, 0x54, 0x04, 0x6C, 0x58,
+       0x04, 0x01, 0x24, 0x81, 0x19, 0x06, 0x0D, 0x01, 0x0B, 0x81, 0x50, 0x01,
+       0x02, 0x81, 0x50, 0x01, 0x82, 0x00, 0x81, 0x50, 0x02, 0x01, 0x50, 0x05,
+       0x14, 0x01, 0x15, 0x81, 0x50, 0x02, 0x01, 0x25, 0x81, 0x50, 0x25, 0x06,
+       0x07, 0x55, 0x01, 0x00, 0x81, 0x52, 0x04, 0x76, 0x24, 0x00, 0x00, 0x01,
+       0x10, 0x81, 0x52, 0x71, 0x2A, 0x25, 0x81, 0x41, 0x06, 0x10, 0x81, 0x21,
+       0x22, 0x25, 0x56, 0x81, 0x51, 0x25, 0x81, 0x50, 0x7C, 0x41, 0x81, 0x4C,
+       0x04, 0x12, 0x25, 0x81, 0x3F, 0x41, 0x81, 0x21, 0x21, 0x25, 0x54, 0x81,
+       0x51, 0x25, 0x81, 0x52, 0x7C, 0x41, 0x81, 0x4C, 0x00, 0x00, 0x81, 0x12,
+       0x01, 0x14, 0x81, 0x52, 0x01, 0x0C, 0x81, 0x51, 0x7C, 0x01, 0x0C, 0x81,
+       0x4C, 0x00, 0x00, 0x49, 0x25, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x58, 0x00,
+       0x81, 0x42, 0x24, 0x04, 0x72, 0x00, 0x25, 0x81, 0x50, 0x81, 0x4C, 0x00,
+       0x00, 0x25, 0x81, 0x52, 0x81, 0x4C, 0x00, 0x01, 0x03, 0x00, 0x3E, 0x24,
+       0x25, 0x01, 0x10, 0x17, 0x06, 0x08, 0x01, 0x04, 0x81, 0x52, 0x02, 0x00,
+       0x81, 0x52, 0x25, 0x01, 0x08, 0x17, 0x06, 0x08, 0x01, 0x03, 0x81, 0x52,
+       0x02, 0x00, 0x81, 0x52, 0x25, 0x01, 0x20, 0x17, 0x06, 0x08, 0x01, 0x05,
+       0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x25, 0x01, 0x80, 0x40, 0x17, 0x06,
+       0x08, 0x01, 0x06, 0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x01, 0x04, 0x17,
+       0x06, 0x08, 0x01, 0x02, 0x81, 0x52, 0x02, 0x00, 0x81, 0x52, 0x00, 0x00,
+       0x25, 0x01, 0x08, 0x47, 0x81, 0x52, 0x81, 0x52, 0x00, 0x00, 0x25, 0x01,
+       0x10, 0x47, 0x81, 0x52, 0x81, 0x50, 0x00, 0x00, 0x25, 0x4A, 0x06, 0x02,
+       0x24, 0x00, 0x81, 0x42, 0x24, 0x04, 0x75
 };
 
 static const uint16_t t0_caddr[] = {
 };
 
 static const uint16_t t0_caddr[] = {
@@ -670,103 +784,111 @@ static const uint16_t t0_caddr[] = {
        112,
        116,
        120,
        112,
        116,
        120,
-       125,
-       130,
-       135,
-       140,
-       145,
-       150,
-       155,
-       160,
-       165,
-       170,
-       175,
-       180,
-       185,
-       190,
-       195,
-       200,
-       205,
-       210,
-       215,
-       220,
-       225,
-       230,
-       235,
-       240,
-       245,
-       250,
-       255,
-       260,
-       265,
+       124,
+       129,
+       134,
+       139,
+       144,
+       149,
+       154,
+       159,
+       164,
+       169,
+       174,
+       179,
+       184,
+       189,
+       194,
+       199,
+       204,
+       209,
+       214,
+       219,
+       224,
+       229,
+       234,
+       239,
+       244,
+       249,
+       254,
+       259,
+       264,
+       269,
        274,
        274,
-       287,
-       291,
-       318,
-       324,
+       279,
+       284,
+       293,
+       306,
+       310,
+       338,
        344,
        344,
-       355,
-       392,
-       495,
-       499,
-       564,
-       579,
-       590,
-       608,
-       637,
-       647,
-       683,
-       693,
-       771,
-       785,
-       791,
-       851,
-       871,
-       924,
-       993,
-       1027,
-       1039,
-       1364,
-       1521,
-       1546,
-       1557,
-       1572,
-       1583,
-       1589,
-       1612,
-       1672,
-       1680,
-       1693,
-       1712,
-       1719,
-       1731,
-       1766,
-       1778,
-       1785,
-       1801,
-       1817,
-       1955,
-       1968,
-       1977,
-       1984,
-       2090,
-       2112,
-       2126,
-       2143,
-       2166,
-       2529,
-       2576,
-       2593,
-       2608,
-       2615,
-       2622,
-       2636,
-       2712,
-       2722,
-       2732
+       365,
+       376,
+       413,
+       548,
+       552,
+       618,
+       633,
+       644,
+       662,
+       691,
+       702,
+       738,
+       748,
+       826,
+       840,
+       847,
+       907,
+       928,
+       981,
+       1067,
+       1096,
+       1131,
+       1143,
+       1482,
+       1641,
+       1667,
+       1898,
+       1913,
+       1924,
+       1930,
+       1999,
+       2022,
+       2083,
+       2091,
+       2105,
+       2125,
+       2133,
+       2145,
+       2182,
+       2194,
+       2201,
+       2218,
+       2235,
+       2374,
+       2384,
+       2398,
+       2408,
+       2416,
+       2522,
+       2544,
+       2558,
+       2575,
+       2598,
+       2635,
+       2677,
+       3049,
+       3096,
+       3113,
+       3128,
+       3135,
+       3142,
+       3218,
+       3228,
+       3238
 };
 
 };
 
-#define T0_INTERPRETED   66
+#define T0_INTERPRETED   80
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
@@ -787,7 +909,7 @@ name(void *ctx) \
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
-T0_DEFENTRY(br_ssl_hs_client_init_main, 141)
+T0_DEFENTRY(br_ssl_hs_client_init_main, 159)
 
 void
 br_ssl_hs_client_run(void *t0ctx)
 
 void
 br_ssl_hs_client_run(void *t0ctx)
@@ -930,6 +1052,15 @@ br_ssl_hs_client_run(void *t0ctx)
                                }
                                break;
                        case 12: {
                                }
                                break;
                        case 12: {
+                               /* <= */
+
+       int32_t b = T0_POPi();
+       int32_t a = T0_POPi();
+       T0_PUSH(-(uint32_t)(a <= b));
+
+                               }
+                               break;
+                       case 13: {
                                /* <> */
 
        uint32_t b = T0_POP();
                                /* <> */
 
        uint32_t b = T0_POP();
@@ -938,7 +1069,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 13: {
+                       case 14: {
                                /* = */
 
        uint32_t b = T0_POP();
                                /* = */
 
        uint32_t b = T0_POP();
@@ -947,7 +1078,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 14: {
+                       case 15: {
                                /* > */
 
        int32_t b = T0_POPi();
                                /* > */
 
        int32_t b = T0_POPi();
@@ -956,7 +1087,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 15: {
+                       case 16: {
                                /* >= */
 
        int32_t b = T0_POPi();
                                /* >= */
 
        int32_t b = T0_POPi();
@@ -965,7 +1096,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 16: {
+                       case 17: {
                                /* >> */
 
        int c = (int)T0_POPi();
                                /* >> */
 
        int c = (int)T0_POPi();
@@ -974,7 +1105,63 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 17: {
+                       case 18: {
+                               /* anchor-dn-append-name */
+
+       size_t len;
+
+       len = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->append_name(
+                       CTX->client_auth_vtable, ENG->pad, len);
+       }
+
+                               }
+                               break;
+                       case 19: {
+                               /* anchor-dn-end-name */
+
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->end_name(
+                       CTX->client_auth_vtable);
+       }
+
+                               }
+                               break;
+                       case 20: {
+                               /* anchor-dn-end-name-list */
+
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->end_name_list(
+                       CTX->client_auth_vtable);
+       }
+
+                               }
+                               break;
+                       case 21: {
+                               /* anchor-dn-start-name */
+
+       size_t len;
+
+       len = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->start_name(
+                       CTX->client_auth_vtable, len);
+       }
+
+                               }
+                               break;
+                       case 22: {
+                               /* anchor-dn-start-name-list */
+
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->start_name_list(
+                       CTX->client_auth_vtable);
+       }
+
+                               }
+                               break;
+                       case 23: {
                                /* and */
 
        uint32_t b = T0_POP();
                                /* and */
 
        uint32_t b = T0_POP();
@@ -983,7 +1170,22 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 18: {
+                       case 24: {
+                               /* begin-cert */
+
+       if (ENG->chain_len == 0) {
+               T0_PUSHi(-1);
+       } else {
+               ENG->cert_cur = ENG->chain->data;
+               ENG->cert_len = ENG->chain->data_len;
+               ENG->chain ++;
+               ENG->chain_len --;
+               T0_PUSH(ENG->cert_len);
+       }
+
+                               }
+                               break;
+                       case 25: {
                                /* bzero */
 
        size_t len = (size_t)T0_POP();
                                /* bzero */
 
        size_t len = (size_t)T0_POP();
@@ -992,19 +1194,19 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 19: {
+                       case 26: {
                                /* can-output? */
 
        T0_PUSHi(-(ENG->hlen_out > 0));
 
                                }
                                break;
                                /* can-output? */
 
        T0_PUSHi(-(ENG->hlen_out > 0));
 
                                }
                                break;
-                       case 20: {
+                       case 27: {
                                /* co */
  T0_CO(); 
                                }
                                break;
                                /* co */
  T0_CO(); 
                                }
                                break;
-                       case 21: {
+                       case 28: {
                                /* compute-Finished-inner */
 
        int prf_id = T0_POP();
                                /* compute-Finished-inner */
 
        int prf_id = T0_POP();
@@ -1027,7 +1229,23 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 22: {
+                       case 29: {
+                               /* copy-cert-chunk */
+
+       size_t clen;
+
+       clen = ENG->cert_len;
+       if (clen > sizeof ENG->pad) {
+               clen = sizeof ENG->pad;
+       }
+       memcpy(ENG->pad, ENG->cert_cur, clen);
+       ENG->cert_cur += clen;
+       ENG->cert_len -= clen;
+       T0_PUSH(clen);
+
+                               }
+                               break;
+                       case 30: {
                                /* data-get8 */
 
        size_t addr = T0_POP();
                                /* data-get8 */
 
        size_t addr = T0_POP();
@@ -1035,14 +1253,28 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 23: {
+                       case 31: {
                                /* discard-input */
 
        ENG->hlen_in = 0;
 
                                }
                                break;
                                /* discard-input */
 
        ENG->hlen_in = 0;
 
                                }
                                break;
-                       case 24: {
+                       case 32: {
+                               /* do-client-sign */
+
+       size_t sig_len;
+
+       sig_len = make_client_sign(CTX);
+       if (sig_len == 0) {
+               br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+               T0_CO();
+       }
+       T0_PUSH(sig_len);
+
+                               }
+                               break;
+                       case 33: {
                                /* do-ecdh */
 
        unsigned prf_id = T0_POP();
                                /* do-ecdh */
 
        unsigned prf_id = T0_POP();
@@ -1059,7 +1291,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 25: {
+                       case 34: {
                                /* do-rsa-encrypt */
 
        int x;
                                /* do-rsa-encrypt */
 
        int x;
@@ -1074,17 +1306,29 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 26: {
+                       case 35: {
+                               /* do-static-ecdh */
+
+       unsigned prf_id = T0_POP();
+
+       if (make_pms_static_ecdh(CTX, prf_id) < 0) {
+               br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+               T0_CO();
+       }
+
+                               }
+                               break;
+                       case 36: {
                                /* drop */
  (void)T0_POP(); 
                                }
                                break;
                                /* drop */
  (void)T0_POP(); 
                                }
                                break;
-                       case 27: {
+                       case 37: {
                                /* dup */
  T0_PUSH(T0_PEEK(0)); 
                                }
                                break;
                                /* dup */
  T0_PUSH(T0_PEEK(0)); 
                                }
                                break;
-                       case 28: {
+                       case 38: {
                                /* fail */
 
        br_ssl_engine_fail(ENG, (int)T0_POPi());
                                /* fail */
 
        br_ssl_engine_fail(ENG, (int)T0_POPi());
@@ -1092,14 +1336,53 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 29: {
+                       case 39: {
                                /* flush-record */
 
        br_ssl_engine_flush_record(ENG);
 
                                }
                                break;
                                /* flush-record */
 
        br_ssl_engine_flush_record(ENG);
 
                                }
                                break;
-                       case 30: {
+                       case 40: {
+                               /* get-client-chain */
+
+       uint32_t auth_types;
+
+       auth_types = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               br_ssl_client_certificate ux;
+
+               (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable,
+                       CTX, auth_types, &ux);
+               CTX->auth_type = (unsigned char)ux.auth_type;
+               CTX->hash_id = (unsigned char)ux.hash_id;
+               ENG->chain = ux.chain;
+               ENG->chain_len = ux.chain_len;
+       } else {
+               CTX->hash_id = 0;
+               ENG->chain_len = 0;
+       }
+
+                               }
+                               break;
+                       case 41: {
+                               /* get-key-type-usages */
+
+       const br_x509_class *xc;
+       const br_x509_pkey *pk;
+       unsigned usages;
+
+       xc = *(ENG->x509ctx);
+       pk = xc->get_pkey(ENG->x509ctx, &usages);
+       if (pk == NULL) {
+               T0_PUSH(0);
+       } else {
+               T0_PUSH(pk->key_type | usages);
+       }
+
+                               }
+                               break;
+                       case 42: {
                                /* get16 */
 
        size_t addr = (size_t)T0_POP();
                                /* get16 */
 
        size_t addr = (size_t)T0_POP();
@@ -1107,7 +1390,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 31: {
+                       case 43: {
                                /* get32 */
 
        size_t addr = (size_t)T0_POP();
                                /* get32 */
 
        size_t addr = (size_t)T0_POP();
@@ -1115,7 +1398,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 32: {
+                       case 44: {
                                /* get8 */
 
        size_t addr = (size_t)T0_POP();
                                /* get8 */
 
        size_t addr = (size_t)T0_POP();
@@ -1123,14 +1406,14 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 33: {
+                       case 45: {
                                /* has-input? */
 
        T0_PUSHi(-(ENG->hlen_in != 0));
 
                                }
                                break;
                                /* has-input? */
 
        T0_PUSHi(-(ENG->hlen_in != 0));
 
                                }
                                break;
-                       case 34: {
+                       case 46: {
                                /* memcmp */
 
        size_t len = (size_t)T0_POP();
                                /* memcmp */
 
        size_t len = (size_t)T0_POP();
@@ -1141,7 +1424,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 35: {
+                       case 47: {
                                /* memcpy */
 
        size_t len = (size_t)T0_POP();
                                /* memcpy */
 
        size_t len = (size_t)T0_POP();
@@ -1151,7 +1434,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 36: {
+                       case 48: {
                                /* mkrand */
 
        size_t len = (size_t)T0_POP();
                                /* mkrand */
 
        size_t len = (size_t)T0_POP();
@@ -1160,21 +1443,21 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 37: {
+                       case 49: {
                                /* more-incoming-bytes? */
 
        T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
 
                                }
                                break;
                                /* more-incoming-bytes? */
 
        T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
 
                                }
                                break;
-                       case 38: {
+                       case 50: {
                                /* multihash-init */
 
        br_multihash_init(&ENG->mhash);
 
                                }
                                break;
                                /* multihash-init */
 
        br_multihash_init(&ENG->mhash);
 
                                }
                                break;
-                       case 39: {
+                       case 51: {
                                /* neg */
 
        uint32_t a = T0_POP();
                                /* neg */
 
        uint32_t a = T0_POP();
@@ -1182,7 +1465,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 40: {
+                       case 52: {
                                /* not */
 
        uint32_t a = T0_POP();
                                /* not */
 
        uint32_t a = T0_POP();
@@ -1190,7 +1473,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 41: {
+                       case 53: {
                                /* or */
 
        uint32_t b = T0_POP();
                                /* or */
 
        uint32_t b = T0_POP();
@@ -1199,12 +1482,12 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 42: {
+                       case 54: {
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
-                       case 43: {
+                       case 55: {
                                /* read-chunk-native */
 
        size_t clen = ENG->hlen_in;
                                /* read-chunk-native */
 
        size_t clen = ENG->hlen_in;
@@ -1228,7 +1511,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 44: {
+                       case 56: {
                                /* read8-native */
 
        if (ENG->hlen_in > 0) {
                                /* read8-native */
 
        if (ENG->hlen_in > 0) {
@@ -1246,7 +1529,20 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 45: {
+                       case 57: {
+                               /* set-server-curve */
+
+       const br_x509_class *xc;
+       const br_x509_pkey *pk;
+
+       xc = *(ENG->x509ctx);
+       pk = xc->get_pkey(ENG->x509ctx, NULL);
+       CTX->server_curve =
+               (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0;
+
+                               }
+                               break;
+                       case 58: {
                                /* set16 */
 
        size_t addr = (size_t)T0_POP();
                                /* set16 */
 
        size_t addr = (size_t)T0_POP();
@@ -1254,7 +1550,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 46: {
+                       case 59: {
                                /* set8 */
 
        size_t addr = (size_t)T0_POP();
                                /* set8 */
 
        size_t addr = (size_t)T0_POP();
@@ -1262,7 +1558,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 47: {
+                       case 60: {
                                /* strlen */
 
        void *str = (unsigned char *)ENG + (size_t)T0_POP();
                                /* strlen */
 
        void *str = (unsigned char *)ENG + (size_t)T0_POP();
@@ -1270,7 +1566,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 48: {
+                       case 61: {
                                /* supported-curves */
 
        uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
                                /* supported-curves */
 
        uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
@@ -1278,7 +1574,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 49: {
+                       case 62: {
                                /* supported-hash-functions */
 
        int i;
                                /* supported-hash-functions */
 
        int i;
@@ -1297,26 +1593,26 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 50: {
+                       case 63: {
                                /* supports-ecdsa? */
 
                                /* supports-ecdsa? */
 
-       T0_PUSHi(-(CTX->iecdsa != 0));
+       T0_PUSHi(-(ENG->iecdsa != 0));
 
                                }
                                break;
 
                                }
                                break;
-                       case 51: {
+                       case 64: {
                                /* supports-rsa-sign? */
 
                                /* supports-rsa-sign? */
 
-       T0_PUSHi(-(CTX->irsavrfy != 0));
+       T0_PUSHi(-(ENG->irsavrfy != 0));
 
                                }
                                break;
 
                                }
                                break;
-                       case 52: {
+                       case 65: {
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
-                       case 53: {
+                       case 66: {
                                /* switch-aesgcm-in */
 
        int is_client, prf_id;
                                /* switch-aesgcm-in */
 
        int is_client, prf_id;
@@ -1330,7 +1626,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 54: {
+                       case 67: {
                                /* switch-aesgcm-out */
 
        int is_client, prf_id;
                                /* switch-aesgcm-out */
 
        int is_client, prf_id;
@@ -1344,7 +1640,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 55: {
+                       case 68: {
                                /* switch-cbc-in */
 
        int is_client, prf_id, mac_id, aes;
                                /* switch-cbc-in */
 
        int is_client, prf_id, mac_id, aes;
@@ -1360,7 +1656,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 56: {
+                       case 69: {
                                /* switch-cbc-out */
 
        int is_client, prf_id, mac_id, aes;
                                /* switch-cbc-out */
 
        int is_client, prf_id, mac_id, aes;
@@ -1376,7 +1672,21 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 57: {
+                       case 70: {
+                               /* total-chain-length */
+
+       size_t u;
+       uint32_t total;
+
+       total = 0;
+       for (u = 0; u < ENG->chain_len; u ++) {
+               total += 3 + (uint32_t)ENG->chain[u].data_len;
+       }
+       T0_PUSH(total);
+
+                               }
+                               break;
+                       case 71: {
                                /* u>> */
 
        int c = (int)T0_POPi();
                                /* u>> */
 
        int c = (int)T0_POPi();
@@ -1385,7 +1695,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 58: {
+                       case 72: {
                                /* verify-SKE-sig */
 
        size_t sig_len = T0_POP();
                                /* verify-SKE-sig */
 
        size_t sig_len = T0_POP();
@@ -1396,7 +1706,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 59: {
+                       case 73: {
                                /* write-blob-chunk */
 
        size_t clen = ENG->hlen_out;
                                /* write-blob-chunk */
 
        size_t clen = ENG->hlen_out;
@@ -1420,7 +1730,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 60: {
+                       case 74: {
                                /* write8-native */
 
        unsigned char x;
                                /* write8-native */
 
        unsigned char x;
@@ -1439,7 +1749,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 61: {
+                       case 75: {
                                /* x509-append */
 
        const br_x509_class *xc;
                                /* x509-append */
 
        const br_x509_class *xc;
@@ -1451,7 +1761,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 62: {
+                       case 76: {
                                /* x509-end-cert */
 
        const br_x509_class *xc;
                                /* x509-end-cert */
 
        const br_x509_class *xc;
@@ -1461,7 +1771,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 63: {
+                       case 77: {
                                /* x509-end-chain */
 
        const br_x509_class *xc;
                                /* x509-end-chain */
 
        const br_x509_class *xc;
@@ -1471,7 +1781,7 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 64: {
+                       case 78: {
                                /* x509-start-cert */
 
        const br_x509_class *xc;
                                /* x509-start-cert */
 
        const br_x509_class *xc;
@@ -1481,13 +1791,15 @@ br_ssl_hs_client_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 65: {
+                       case 79: {
                                /* x509-start-chain */
 
        const br_x509_class *xc;
                                /* x509-start-chain */
 
        const br_x509_class *xc;
+       uint32_t bc;
 
 
+       bc = T0_POP();
        xc = *(ENG->x509ctx);
        xc = *(ENG->x509ctx);
-       xc->start_chain(ENG->x509ctx, T0_POP(), ENG->server_name);
+       xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
 
                                }
                                break;
 
                                }
                                break;
index ea9f5b5..37c554c 100644 (file)
@@ -55,7 +55,7 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
        size_t nlen, u;
 
        xc = ctx->eng.x509ctx;
        size_t nlen, u;
 
        xc = ctx->eng.x509ctx;
-       pk = (*xc)->get_pkey(xc);
+       pk = (*xc)->get_pkey(xc, NULL);
 
        /*
         * Compute actual RSA key length, in case there are leading zeros.
 
        /*
         * Compute actual RSA key length, in case there are leading zeros.
@@ -145,9 +145,11 @@ static const unsigned char *HASH_OID[] = {
 
 /*
  * Check the RSA signature on the ServerKeyExchange message.
 
 /*
  * Check the RSA signature on the ServerKeyExchange message.
+ *
  *   hash      hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
  *   use_rsa   non-zero for RSA signature, zero for ECDSA
  *   sig_len   signature length (in bytes); signature value is in the pad
  *   hash      hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
  *   use_rsa   non-zero for RSA signature, zero for ECDSA
  *   sig_len   signature length (in bytes); signature value is in the pad
+ *
  * Returned value is 0 on success, or an error code.
  */
 static int
  * Returned value is 0 on success, or an error code.
  */
 static int
@@ -161,7 +163,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,
        size_t hv_len;
 
        xc = ctx->eng.x509ctx;
        size_t hv_len;
 
        xc = ctx->eng.x509ctx;
-       pk = (*xc)->get_pkey(xc);
+       pk = (*xc)->get_pkey(xc, NULL);
        br_multihash_zero(&mhc);
        br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
        br_multihash_init(&mhc);
        br_multihash_zero(&mhc);
        br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
        br_multihash_init(&mhc);
@@ -198,14 +200,14 @@ verify_SKE_sig(br_ssl_client_context *ctx,
                } else {
                        hash_oid = NULL;
                }
                } else {
                        hash_oid = NULL;
                }
-               if (!ctx->irsavrfy(ctx->eng.pad, sig_len,
+               if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
                        hash_oid, hv_len, &pk->key.rsa, tmp)
                        || memcmp(tmp, hv, hv_len) != 0)
                {
                        return BR_ERR_BAD_SIGNATURE;
                }
        } else {
                        hash_oid, hv_len, &pk->key.rsa, tmp)
                        || memcmp(tmp, hv, hv_len) != 0)
                {
                        return BR_ERR_BAD_SIGNATURE;
                }
        } else {
-               if (!ctx->iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
+               if (!ctx->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
                        ctx->eng.pad, sig_len))
                {
                        return BR_ERR_BAD_SIGNATURE;
                        ctx->eng.pad, sig_len))
                {
                        return BR_ERR_BAD_SIGNATURE;
@@ -215,7 +217,7 @@ verify_SKE_sig(br_ssl_client_context *ctx,
 }
 
 /*
 }
 
 /*
- * Perform client-size ECDH (or ECDHE). The point that should be sent to
+ * Perform client-side ECDH (or ECDHE). The point that should be sent to
  * the server is written in the pad; returned value is either the point
  * length (in bytes), or -x on error, with 'x' being an error code.
  *
  * the server is written in the pad; returned value is either the point
  * length (in bytes), or -x on error, with 'x' being an error code.
  *
@@ -241,7 +243,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
                const br_x509_pkey *pk;
 
                xc = ctx->eng.x509ctx;
                const br_x509_pkey *pk;
 
                xc = ctx->eng.x509ctx;
-               pk = (*xc)->get_pkey(xc);
+               pk = (*xc)->get_pkey(xc, NULL);
                curve = pk->key.ec.curve;
                point_src = pk->key.ec.q;
                point_len = pk->key.ec.qlen;
                curve = pk->key.ec.curve;
                point_src = pk->key.ec.q;
                point_len = pk->key.ec.qlen;
@@ -292,6 +294,73 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
        return (int)glen;
 }
 
        return (int)glen;
 }
 
+/*
+ * Perform full static ECDH. This occurs only in the context of client
+ * authentication with certificates: the server uses an EC public key,
+ * the cipher suite is of type ECDH (not ECDHE), the server requested a
+ * client certificate and accepts static ECDH, the client has a
+ * certificate with an EC public key in the same curve, and accepts
+ * static ECDH as well.
+ *
+ * Returned value is 0 on success, -1 on error.
+ */
+static int
+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
+{
+       unsigned char point[133];
+       size_t point_len;
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       point_len = pk->key.ec.qlen;
+       if (point_len > sizeof point) {
+               return -1;
+       }
+       memcpy(point, pk->key.ec.q, point_len);
+       if (!(*ctx->client_auth_vtable)->do_keyx(
+               ctx->client_auth_vtable, point, point_len))
+       {
+               return -1;
+       }
+       br_ssl_engine_compute_master(&ctx->eng,
+               prf_id, point + 1, point_len >> 1);
+       return 0;
+}
+
+/*
+ * Compute the client-side signature. This is invoked only when a
+ * signature-based client authentication was selected. The computed
+ * signature is in the pad; its length (in bytes) is returned. On
+ * error, 0 is returned.
+ */
+static size_t
+make_client_sign(br_ssl_client_context *ctx)
+{
+       size_t hv_len;
+
+       /*
+        * Compute hash of handshake messages so far. This "cannot" fail
+        * because the list of supported hash functions provided to the
+        * client certificate handler was trimmed to include only the
+        * hash functions that the multi-hasher supports.
+        */
+       if (ctx->hash_id) {
+               hv_len = br_multihash_out(&ctx->eng.mhash,
+                       ctx->hash_id, ctx->eng.pad);
+       } else {
+               br_multihash_out(&ctx->eng.mhash,
+                       br_md5_ID, ctx->eng.pad);
+               br_multihash_out(&ctx->eng.mhash,
+                       br_sha1_ID, ctx->eng.pad + 16);
+               hv_len = 36;
+       }
+       return (*ctx->client_auth_vtable)->do_sign(
+               ctx->client_auth_vtable, ctx->hash_id, hv_len,
+               ctx->eng.pad, sizeof ctx->eng.pad);
+}
+
 }
 
 \ =======================================================================
 }
 
 \ =======================================================================
@@ -303,6 +372,9 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
        postpone literal postpone ; ;
 
 addr-ctx: min_clienthello_len
        postpone literal postpone ; ;
 
 addr-ctx: min_clienthello_len
+addr-ctx: hashes
+addr-ctx: auth_type
+addr-ctx: hash_id
 
 \ Length of the Secure Renegotiation extension. This is 5 for the
 \ first handshake, 17 for a renegotiation (if the server supports the
 
 \ Length of the Secure Renegotiation extension. This is 5 for the
 \ first handshake, 17 for a renegotiation (if the server supports the
@@ -319,16 +391,6 @@ addr-ctx: min_clienthello_len
 : ext-frag-length ( -- len )
        addr-log_max_frag_len get8 14 = if 0 else 5 then ;
 
 : ext-frag-length ( -- len )
        addr-log_max_frag_len get8 14 = if 0 else 5 then ;
 
-\ Test support for RSA signatures.
-cc: supports-rsa-sign? ( -- bool ) {
-       T0_PUSHi(-(CTX->irsavrfy != 0));
-}
-
-\ Test support for ECDSA signatures.
-cc: supports-ecdsa? ( -- bool ) {
-       T0_PUSHi(-(CTX->iecdsa != 0));
-}
-
 \ Length of Signatures extension.
 : ext-signatures-length ( -- len )
        supported-hash-functions { x } drop
 \ Length of Signatures extension.
 : ext-signatures-length ( -- len )
        supported-hash-functions { x } drop
@@ -709,80 +771,26 @@ cc: DEBUG-BLOB ( addr len -- ) {
        resume
        ;
 
        resume
        ;
 
-cc: x509-start-chain ( expected-key-type -- ) {
-       const br_x509_class *xc;
-
-       xc = *(ENG->x509ctx);
-       xc->start_chain(ENG->x509ctx, T0_POP(), ENG->server_name);
-}
-
-cc: x509-start-cert ( length -- ) {
-       const br_x509_class *xc;
-
-       xc = *(ENG->x509ctx);
-       xc->start_cert(ENG->x509ctx, T0_POP());
-}
-
-cc: x509-append ( length -- ) {
-       const br_x509_class *xc;
-       size_t len;
-
-       xc = *(ENG->x509ctx);
-       len = T0_POP();
-       xc->append(ENG->x509ctx, ENG->pad, len);
-}
-
-cc: x509-end-cert ( -- ) {
-       const br_x509_class *xc;
-
-       xc = *(ENG->x509ctx);
-       xc->end_cert(ENG->x509ctx);
-}
-
-cc: x509-end-chain ( -- err ) {
+cc: set-server-curve ( -- ) {
        const br_x509_class *xc;
        const br_x509_class *xc;
+       const br_x509_pkey *pk;
 
        xc = *(ENG->x509ctx);
 
        xc = *(ENG->x509ctx);
-       T0_PUSH(xc->end_chain(ENG->x509ctx));
+       pk = xc->get_pkey(ENG->x509ctx, NULL);
+       CTX->server_curve =
+               (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0;
 }
 
 }
 
-\ Parse Certificate
-: read-Certificate ( -- )
-       \ Get header, and check message type.
-       read-handshake-header 11 = ifnot ERR_UNEXPECTED fail then
-
-       \ Start processing the chain through the X.509 engine.
+\ Read Certificate message from server.
+: read-Certificate-from-server ( -- )
        addr-cipher_suite get16 expected-key-type
        addr-cipher_suite get16 expected-key-type
-       x509-start-chain
-
-       \ Total chain length is a 24-bit integer.
-       read24 open-elt
-       begin
-               dup while
-               read24 open-elt
-               dup x509-start-cert
-
-               \ We read the certificate by chunks through the pad, so
-               \ as to use the existing reading function (read-blob)
-               \ that also ensures proper hashing.
-               begin
-                       dup while
-                       dup 256 > if 256 else dup then { len }
-                       addr-pad len read-blob
-                       len x509-append
-               repeat
-               close-elt
-               x509-end-cert
-       repeat
-
-       \ We must close the chain AND the handshake message.
-       close-elt
-       close-elt
+       -1 read-Certificate
+       dup 0< if neg fail then
+       dup ifnot ERR_UNEXPECTED fail then
+       over and <> if ERR_WRONG_KEY_USAGE fail then
 
 
-       \ Chain processing is finished; get the error code.
-       x509-end-chain
-       dup if fail then drop
-       ;
+       \ Set server curve (used for static ECDH).
+       set-server-curve ;
 
 \ Verify signature on ECDHE point sent by the server.
 \   'hash' is the hash function to use (1 to 6, or 0 for RSA with MD5+SHA-1)
 
 \ Verify signature on ECDHE point sent by the server.
 \   'hash' is the hash function to use (1 to 6, or 0 for RSA with MD5+SHA-1)
@@ -851,15 +859,166 @@ cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) {
 
        close-elt ;
 
 
        close-elt ;
 
+\ Client certificate: start processing of anchor names.
+cc: anchor-dn-start-name-list ( -- ) {
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->start_name_list(
+                       CTX->client_auth_vtable);
+       }
+}
+
+\ Client certificate: start a new anchor DN (length is 16-bit).
+cc: anchor-dn-start-name ( length -- ) {
+       size_t len;
+
+       len = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->start_name(
+                       CTX->client_auth_vtable, len);
+       }
+}
+
+\ Client certificate: push some data for current anchor DN.
+cc: anchor-dn-append-name ( length -- ) {
+       size_t len;
+
+       len = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->append_name(
+                       CTX->client_auth_vtable, ENG->pad, len);
+       }
+}
+
+\ Client certificate: end current anchor DN.
+cc: anchor-dn-end-name ( -- ) {
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->end_name(
+                       CTX->client_auth_vtable);
+       }
+}
+
+\ Client certificate: end list of anchor DN.
+cc: anchor-dn-end-name-list ( -- ) {
+       if (CTX->client_auth_vtable != NULL) {
+               (*CTX->client_auth_vtable)->end_name_list(
+                       CTX->client_auth_vtable);
+       }
+}
+
+\ Client certificate: obtain the client certificate chain.
+cc: get-client-chain ( auth_types -- ) {
+       uint32_t auth_types;
+
+       auth_types = T0_POP();
+       if (CTX->client_auth_vtable != NULL) {
+               br_ssl_client_certificate ux;
+
+               (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable,
+                       CTX, auth_types, &ux);
+               CTX->auth_type = (unsigned char)ux.auth_type;
+               CTX->hash_id = (unsigned char)ux.hash_id;
+               ENG->chain = ux.chain;
+               ENG->chain_len = ux.chain_len;
+       } else {
+               CTX->hash_id = 0;
+               ENG->chain_len = 0;
+       }
+}
+
 \ Parse CertificateRequest. Header has already been read.
 : read-contents-CertificateRequest ( lim -- )
 \ Parse CertificateRequest. Header has already been read.
 : read-contents-CertificateRequest ( lim -- )
-       \ TODO: implement client certificates. Right now, we simply
-       \ drop the complete message.
-       begin dup while read8 drop repeat drop ;
+       \ Read supported client authentification types. We keep only
+       \ RSA, ECDSA, and ECDH.
+       0 { auth_types }
+       read8 open-elt
+       begin dup while
+               read8 case
+                       1  of 0x0000FF endof
+                       64 of 0x00FF00 endof
+                       65 of 0x010000 endof
+                       66 of 0x020000 endof
+                       0 swap
+               endcase
+               auth_types or >auth_types
+       repeat
+       close-elt
+
+       \ Full static ECDH is allowed only if the cipher suite is ECDH
+       \ (not ECDHE). It would be theoretically feasible to use static
+       \ ECDH on the client side with an ephemeral key pair from the
+       \ server, but RFC 4492 (section 3) forbids it because ECDHE suites
+       \ are supposed to provide forward secrecy, and static ECDH would
+       \ negate that property.
+       addr-cipher_suite get16 use-ecdh? ifnot
+               auth_types 0xFFFF and >auth_types
+       then
+
+       \ Note: if the cipher suite is ECDH, then the X.509 validation
+       \ engine was invoked with the BR_KEYTYPE_EC | BR_KEYTYPE_KEYX
+       \ combination, so the server's public key has already been
+       \ checked to be fit for a key exchange.
+
+       \ With TLS 1.2:
+       \  - rsa_fixed_ecdh and ecdsa_fixed_ecdh are synoymous.
+       \  - There is an explicit list of supported sign+hash.
+       \ With TLS 1.0,
+       addr-version get16 0x0303 >= if
+               \ With TLS 1.2:
+               \  - There is an explicit list of supported sign+hash.
+               \  - The ECDH flags must be adjusted for RSA/ECDSA
+               \    support.
+               read-list-sign-algos dup addr-hashes set16
+
+               \ Trim down the list depending on what hash functions
+               \ we support (since the hashing itself is done by the SSL
+               \ engine, not by the certificate handler).
+               supported-hash-functions drop dup 8 << or 0x030000 or and
+
+               auth_types and
+               auth_types 0x030000 and if
+                       dup 0x0000FF and if 0x010000 or then
+                       dup 0x00FF00 and if 0x020000 or then
+               then
+               >auth_types
+       else
+               \ TLS 1.0 or 1.1. The hash function is fixed for signatures
+               \ (MD5+SHA-1 for RSA, SHA-1 for ECDSA).
+               auth_types 0x030401 and >auth_types
+       then
+
+       \ Parse list of anchor DN.
+       anchor-dn-start-name-list
+       read16 open-elt
+       begin dup while
+               read16 open-elt
+               dup anchor-dn-start-name
+
+               \ We read the DN by chunks through the pad, so
+               \ as to use the existing reading function (read-blob)
+               \ that also ensures proper hashing.
+               begin
+                       dup while
+                       dup 256 > if 256 else dup then { len }
+                       addr-pad len read-blob
+                       len anchor-dn-append-name
+               repeat
+               close-elt
+               anchor-dn-end-name
+       repeat
+       close-elt
+       anchor-dn-end-name-list
+
+       \ We should have reached the message end.
+       close-elt
+
+       \ Obtain the client chain.
+       auth_types get-client-chain
+       ;
 
 
+\ (obsolete)
 \ Write an empty Certificate message.
 \ Write an empty Certificate message.
-: write-empty-Certificate ( -- )
-       11 write8 3 write24 0 write24 ;
+: write-empty-Certificate ( -- )
+\      11 write8 3 write24 0 write24 ;
 
 cc: do-rsa-encrypt ( prf_id -- nlen ) {
        int x;
 
 cc: do-rsa-encrypt ( prf_id -- nlen ) {
        int x;
@@ -887,7 +1046,27 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
        }
 }
 
        }
 }
 
-\ Write ClientKeyExchange
+cc: do-static-ecdh ( prf-id -- ) {
+       unsigned prf_id = T0_POP();
+
+       if (make_pms_static_ecdh(CTX, prf_id) < 0) {
+               br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+               T0_CO();
+       }
+}
+
+cc: do-client-sign ( -- sig_len ) {
+       size_t sig_len;
+
+       sig_len = make_client_sign(CTX);
+       if (sig_len == 0) {
+               br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+               T0_CO();
+       }
+       T0_PUSH(sig_len);
+}
+
+\ Write ClientKeyExchange.
 : write-ClientKeyExchange ( -- )
        16 write8
        addr-cipher_suite get16
 : write-ClientKeyExchange ( -- )
        16 write8
        addr-cipher_suite get16
@@ -903,6 +1082,20 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
                addr-pad swap write-blob
        then ;
 
                addr-pad swap write-blob
        then ;
 
+\ Write CertificateVerify. This is invoked only if a client certificate
+\ was requested and sent, and the authentication is not full static ECDH.
+: write-CertificateVerify ( -- )
+       do-client-sign
+       15 write8 dup
+       addr-version get16 0x0303 >= if
+               4 + write24
+               addr-hash_id get8 write8
+               addr-auth_type get8 write8
+       else
+               2+ write24
+       then
+       dup write16 addr-pad swap write-blob ;
+
 \ =======================================================================
 
 \ Perform a handshake.
 \ =======================================================================
 
 \ Perform a handshake.
@@ -924,7 +1117,9 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
 
                \ Not a session resumption.
 
 
                \ Not a session resumption.
 
-               read-Certificate
+               \ Read certificate; then check key type and usages against
+               \ cipher suite.
+               read-Certificate-from-server
 
                \ Depending on cipher suite, we may now expect a
                \ ServerKeyExchange.
 
                \ Depending on cipher suite, we may now expect a
                \ ServerKeyExchange.
@@ -956,12 +1151,27 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
                more-incoming-bytes? if ERR_UNEXPECTED fail then
 
                seen-CR if
                more-incoming-bytes? if ERR_UNEXPECTED fail then
 
                seen-CR if
-                       \ TODO: client certificate support.
-                       write-empty-Certificate
+                       \ If the server requested a client certificate, then
+                       \ we must write a Certificate message (it may be
+                       \ empty).
+                       write-Certificate
+
+                       \ If using static ECDH, then the ClientKeyExchange
+                       \ is empty, and there is no CertificateVerify.
+                       \ Otherwise, there is a ClientKeyExchange; there
+                       \ will then be a CertificateVerify if a client chain
+                       \ was indeed sent.
+                       addr-hash_id get8 0xFF = if
+                               drop
+                               16 write8 0 write24
+                               addr-cipher_suite get16 prf-id do-static-ecdh
+                       else
+                               write-ClientKeyExchange
+                               if write-CertificateVerify then
+                       then
+               else
+                       write-ClientKeyExchange
                then
                then
-               write-ClientKeyExchange
-
-               \ TODO: CertificateVerify
 
                -1 write-CCS-Finished
                -1 read-CCS-Finished
 
                -1 write-CCS-Finished
                -1 read-CCS-Finished
index 1eb5347..da6fc8a 100644 (file)
@@ -145,12 +145,8 @@ addr-eng: version_max
 addr-eng: suites_buf
 addr-eng: suites_num
 addr-eng: server_name
 addr-eng: suites_buf
 addr-eng: suites_num
 addr-eng: server_name
-\ addr-eng: version
-\ addr-eng: cipher_suite
 addr-eng: client_random
 addr-eng: server_random
 addr-eng: client_random
 addr-eng: server_random
-\ addr-eng: session_id_len
-\ addr-eng: session_id
 addr-eng: ecdhe_curve
 addr-eng: ecdhe_point
 addr-eng: ecdhe_point_len
 addr-eng: ecdhe_curve
 addr-eng: ecdhe_point
 addr-eng: ecdhe_point_len
@@ -212,6 +208,9 @@ err: ERR_LIMIT_EXCEEDED
 err: ERR_BAD_FINISHED
 err: ERR_RESUME_MISMATCH
 err: ERR_INVALID_ALGORITHM
 err: ERR_BAD_FINISHED
 err: ERR_RESUME_MISMATCH
 err: ERR_INVALID_ALGORITHM
+err: ERR_BAD_SIGNATURE
+err: ERR_WRONG_KEY_USAGE
+err: ERR_NO_CLIENT_AUTH
 
 \ Get supported curves (bit mask).
 cc: supported-curves ( -- x ) {
 
 \ Get supported curves (bit mask).
 cc: supported-curves ( -- x ) {
@@ -220,6 +219,7 @@ cc: supported-curves ( -- x ) {
 }
 
 \ Get supported hash functions (bit mask and number).
 }
 
 \ Get supported hash functions (bit mask and number).
+\ Note: this (on purpose) skips MD5.
 cc: supported-hash-functions ( -- x num ) {
        int i;
        unsigned x, num;
 cc: supported-hash-functions ( -- x num ) {
        int i;
        unsigned x, num;
@@ -236,6 +236,16 @@ cc: supported-hash-functions ( -- x num ) {
        T0_PUSH(num);
 }
 
        T0_PUSH(num);
 }
 
+\ Test support for RSA signatures.
+cc: supports-rsa-sign? ( -- bool ) {
+       T0_PUSHi(-(ENG->irsavrfy != 0));
+}
+
+\ Test support for ECDSA signatures.
+cc: supports-ecdsa? ( -- bool ) {
+       T0_PUSHi(-(ENG->iecdsa != 0));
+}
+
 \ (Re)initialise the multihasher.
 cc: multihash-init ( -- ) {
        br_multihash_init(&ENG->mhash);
 \ (Re)initialise the multihasher.
 cc: multihash-init ( -- ) {
        br_multihash_init(&ENG->mhash);
@@ -1020,3 +1030,186 @@ cc: compute-Finished-inner ( from_client prf_id -- ) {
        22 wait-rectype-out
        write-Finished
        flush-record ;
        22 wait-rectype-out
        write-Finished
        flush-record ;
+
+\ Read and parse a list of supported signature algorithms (with hash
+\ functions). The resulting bit field is returned.
+: read-list-sign-algos ( lim -- lim value )
+       0 { hashes }
+       read16 open-elt
+       begin dup while
+               read8 { hash } read8 { sign }
+               \ We keep the value if the signature is either 1 (RSA)
+               \ or 3 (ECDSA), and the hash is one of the SHA-* functions
+               \ (2 to 6, from SHA-1 to SHA-512); we reject MD5.
+               hash 2 >= hash 6 <= and
+               sign 1 = sign 3 = or
+               and if
+                       hashes 1 sign 1- 2 << hash + << or >hashes
+               then
+       repeat
+       close-elt
+       hashes ;
+
+\ =======================================================================
+
+\ Compute total chain length. This includes the individual certificate
+\ headers, but not the total chain header. This also sets the cert_cur,
+\ cert_len and chain_len context fields.
+cc: total-chain-length ( -- len ) {
+       size_t u;
+       uint32_t total;
+
+       total = 0;
+       for (u = 0; u < ENG->chain_len; u ++) {
+               total += 3 + (uint32_t)ENG->chain[u].data_len;
+       }
+       T0_PUSH(total);
+}
+
+\ Get length for current certificate in the chain; if the chain end was
+\ reached, then this returns -1.
+cc: begin-cert ( -- len ) {
+       if (ENG->chain_len == 0) {
+               T0_PUSHi(-1);
+       } else {
+               ENG->cert_cur = ENG->chain->data;
+               ENG->cert_len = ENG->chain->data_len;
+               ENG->chain ++;
+               ENG->chain_len --;
+               T0_PUSH(ENG->cert_len);
+       }
+}
+
+\ Copy a chunk of certificate data into the pad. Returned value is the
+\ chunk length, or 0 if the certificate end is reached.
+cc: copy-cert-chunk ( -- len ) {
+       size_t clen;
+
+       clen = ENG->cert_len;
+       if (clen > sizeof ENG->pad) {
+               clen = sizeof ENG->pad;
+       }
+       memcpy(ENG->pad, ENG->cert_cur, clen);
+       ENG->cert_cur += clen;
+       ENG->cert_len -= clen;
+       T0_PUSH(clen);
+}
+
+\ Write a Certificate message. Total chain length (excluding the 3-byte
+\ header) is returned; it is 0 if the chain is empty.
+: write-Certificate ( -- total_chain_len )
+       11 write8
+       total-chain-length dup
+       dup 3 + write24 write24
+       begin
+               begin-cert
+               dup 0< if drop ret then write24
+               begin copy-cert-chunk dup while
+                       addr-pad swap write-blob
+               repeat
+               drop
+       again ;
+
+cc: x509-start-chain ( by_client -- ) {
+       const br_x509_class *xc;
+       uint32_t bc;
+
+       bc = T0_POP();
+       xc = *(ENG->x509ctx);
+       xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
+}
+
+cc: x509-start-cert ( length -- ) {
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       xc->start_cert(ENG->x509ctx, T0_POP());
+}
+
+cc: x509-append ( length -- ) {
+       const br_x509_class *xc;
+       size_t len;
+
+       xc = *(ENG->x509ctx);
+       len = T0_POP();
+       xc->append(ENG->x509ctx, ENG->pad, len);
+}
+
+cc: x509-end-cert ( -- ) {
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       xc->end_cert(ENG->x509ctx);
+}
+
+cc: x509-end-chain ( -- err ) {
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       T0_PUSH(xc->end_chain(ENG->x509ctx));
+}
+
+cc: get-key-type-usages ( -- key-type-usages ) {
+       const br_x509_class *xc;
+       const br_x509_pkey *pk;
+       unsigned usages;
+
+       xc = *(ENG->x509ctx);
+       pk = xc->get_pkey(ENG->x509ctx, &usages);
+       if (pk == NULL) {
+               T0_PUSH(0);
+       } else {
+               T0_PUSH(pk->key_type | usages);
+       }
+}
+
+\ Read a Certificate message.
+\ Parameter: non-zero if this is a read by the client of a certificate
+\ sent by the server; zero otherwise.
+\ Returned value:
+\   - Empty: 0
+\   - Valid: combination of key type and allowed key usages.
+\   - Invalid: negative (-x for error code x)
+: read-Certificate ( by_client -- key-type-usages )
+       \ Get header, and check message type.
+       read-handshake-header 11 = ifnot ERR_UNEXPECTED fail then
+
+       \ If the chain is empty, do some special processing.
+       dup 3 = if
+               read24 if ERR_BAD_PARAM fail then
+               swap drop ret
+       then
+
+       \ Start processing the chain through the X.509 engine.
+       swap x509-start-chain
+
+       \ Total chain length is a 24-bit integer.
+       read24 open-elt
+       begin
+               dup while
+               read24 open-elt
+               dup x509-start-cert
+
+               \ We read the certificate by chunks through the pad, so
+               \ as to use the existing reading function (read-blob)
+               \ that also ensures proper hashing.
+               begin
+                       dup while
+                       dup 256 > if 256 else dup then { len }
+                       addr-pad len read-blob
+                       len x509-append
+               repeat
+               close-elt
+               x509-end-cert
+       repeat
+
+       \ We must close the chain AND the handshake message.
+       close-elt
+       close-elt
+
+       \ Chain processing is finished; get the error code.
+       x509-end-chain
+       dup if neg ret then drop
+
+       \ Return key type and usages.
+       get-key-type-usages ;
index a46734d..14dcf33 100644 (file)
@@ -195,6 +195,35 @@ do_ecdh(br_ssl_server_context *ctx, int prf_id,
        ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
 }
 
        ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
 }
 
+/*
+ * Do the full static ECDH key exchange. When this function is called,
+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),
+ * and the client's public key (from its certificate) has type EC and is
+ * apt for key exchange.
+ */
+static void
+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)
+{
+       unsigned char cpoint[133];
+       size_t cpoint_len;
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       cpoint_len = pk->key.ec.qlen;
+       if (cpoint_len > sizeof cpoint) {
+               /*
+                * If the point is larger than our buffer then we need to
+                * restrict it. Length 2 is not a valid point length, so
+                * the ECDH will fail.
+                */
+               cpoint_len = 2;
+       }
+       memcpy(cpoint, pk->key.ec.q, cpoint_len);
+       do_ecdh(ctx, prf_id, cpoint, cpoint_len);
+}
+
 /*
  * Do the ECDHE key exchange (part 1: generation of transient key, and
  * computing of the point to send to the client). Returned value is the
 /*
  * Do the ECDHE key exchange (part 1: generation of transient key, and
  * computing of the point to send to the client). Returned value is the
@@ -313,6 +342,94 @@ do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
        memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
 }
 
        memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
 }
 
+/*
+ * Offset for hash value within the pad (when obtaining all hash values,
+ * in preparation for verification of the CertificateVerify message).
+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value
+ * is used to get the total length.
+ */
+static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 };
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+       HASH_OID_SHA1,
+       HASH_OID_SHA224,
+       HASH_OID_SHA256,
+       HASH_OID_SHA384,
+       HASH_OID_SHA512
+};
+
+/*
+ * Verify the signature in CertificateVerify. Returned value is 0 on
+ * success, or a non-zero error code. Lack of implementation of the
+ * designated signature algorithm is reported as a "bad signature"
+ * error (because it means that the peer did not honour our advertised
+ * set of supported signature algorithms).
+ */
+static int
+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)
+{
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+       int id;
+
+       id = ctx->hash_CV_id;
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       if (pk->key_type == BR_KEYTYPE_RSA) {
+               unsigned char tmp[64];
+               const unsigned char *hash_oid;
+
+               if (id == 0) {
+                       hash_oid = NULL;
+               } else {
+                       hash_oid = HASH_OID[id - 2];
+               }
+               if (ctx->eng.irsavrfy == 0) {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+               if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+                       hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp)
+                       || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0)
+               {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+       } else {
+               if (ctx->eng.iecdsa == 0) {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+               if (!ctx->eng.iecdsa(ctx->eng.iec,
+                       ctx->hash_CV, ctx->hash_CV_len,
+                       &pk->key.ec, ctx->eng.pad, sig_len))
+               {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+       }
+       return 0;
+}
+
 
 
 static const uint8_t t0_datablock[] = {
 
 
 static const uint8_t t0_datablock[] = {
@@ -332,19 +449,23 @@ static const uint8_t t0_datablock[] = {
 };
 
 static const uint8_t t0_codeblock[] = {
 };
 
 static const uint8_t t0_codeblock[] = {
-       0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01,
-       0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08,
+       0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01,
+       0x00, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x08,
        0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
        0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
-       0x21, 0x21, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00,
+       0x28, 0x28, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00,
        0x01, T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01,
        0x01, T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01,
+       T0_INT1(BR_ERR_BAD_SIGNATURE), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01,
-       T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),
+       T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01,
+       T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,
+       T0_INT1(BR_ERR_NO_CLIENT_AUTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),
        0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
        0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
+       T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
        T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
@@ -363,7 +484,7 @@ static const uint8_t t0_codeblock[] = {
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)),
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)),
-       0x00, 0x00, 0x5D, 0x01,
+       0x00, 0x00, 0x73, 0x01,
        T0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00,
        T0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
        0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00,
@@ -393,203 +514,257 @@ static const uint8_t t0_codeblock[] = {
        T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
        T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
-       0x00, 0x00, 0x09, 0x22, 0x44, 0x06, 0x02, 0x50, 0x23, 0x00, 0x00, 0x01,
-       0x01, 0x00, 0x01, 0x03, 0x00, 0x7B, 0x22, 0x4A, 0x3B, 0x7F, 0x22, 0x05,
-       0x04, 0x4B, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0x7F, 0x00,
-       0x4A, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x50, 0x23, 0x00, 0x00, 0x22, 0x6C,
-       0x3B, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x3B, 0x5A, 0x25, 0x81, 0x07, 0x19,
-       0x67, 0x01, 0x0C, 0x2A, 0x00, 0x00, 0x22, 0x1B, 0x01, 0x08, 0x0B, 0x3B,
-       0x48, 0x1B, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, 0x59, 0x38, 0x24,
-       0x16, 0x2F, 0x06, 0x08, 0x02, 0x00, 0x81, 0x26, 0x03, 0x00, 0x04, 0x74,
-       0x01, 0x00, 0x81, 0x1E, 0x02, 0x00, 0x22, 0x16, 0x12, 0x06, 0x02, 0x54,
-       0x23, 0x81, 0x26, 0x04, 0x75, 0x00, 0x01, 0x00, 0x59, 0x38, 0x01, 0x16,
-       0x6A, 0x38, 0x2D, 0x81, 0x0B, 0x2C, 0x06, 0x02, 0x56, 0x23, 0x06, 0x0C,
-       0x81, 0x2C, 0x01, 0x00, 0x81, 0x29, 0x01, 0x00, 0x81, 0x0A, 0x04, 0x14,
-       0x81, 0x2C, 0x81, 0x2A, 0x81, 0x2E, 0x81, 0x2D, 0x24, 0x81, 0x0C, 0x01,
-       0x00, 0x81, 0x0A, 0x01, 0x00, 0x81, 0x29, 0x34, 0x01, 0x01, 0x59, 0x38,
-       0x01, 0x17, 0x6A, 0x38, 0x00, 0x00, 0x31, 0x31, 0x00, 0x01, 0x03, 0x00,
-       0x24, 0x16, 0x2F, 0x06, 0x05, 0x81, 0x25, 0x21, 0x04, 0x77, 0x01, 0x02,
-       0x02, 0x00, 0x81, 0x1D, 0x16, 0x2F, 0x06, 0x05, 0x81, 0x25, 0x21, 0x04,
-       0x77, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x23, 0x00, 0x00, 0x63, 0x26,
-       0x3B, 0x11, 0x01, 0x01, 0x12, 0x2E, 0x00, 0x00, 0x01, 0x7F, 0x81, 0x01,
-       0x81, 0x25, 0x22, 0x01, 0x07, 0x12, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x0A,
-       0x21, 0x01, 0x10, 0x12, 0x06, 0x02, 0x81, 0x1C, 0x04, 0x2E, 0x01, 0x01,
-       0x31, 0x0E, 0x06, 0x25, 0x21, 0x21, 0x6B, 0x27, 0x01, 0x01, 0x0E, 0x01,
-       0x01, 0x81, 0x04, 0x30, 0x06, 0x11, 0x24, 0x16, 0x2F, 0x06, 0x05, 0x81,
-       0x25, 0x21, 0x04, 0x77, 0x01, 0x80, 0x64, 0x81, 0x1E, 0x04, 0x04, 0x01,
-       0x00, 0x81, 0x01, 0x04, 0x03, 0x56, 0x23, 0x21, 0x04, 0xFF, 0x39, 0x01,
-       0x22, 0x03, 0x00, 0x09, 0x22, 0x44, 0x06, 0x02, 0x50, 0x23, 0x02, 0x00,
-       0x00, 0x00, 0x7C, 0x01, 0x0F, 0x12, 0x00, 0x00, 0x58, 0x27, 0x01, 0x00,
-       0x31, 0x0E, 0x06, 0x10, 0x21, 0x22, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x21,
-       0x01, 0x02, 0x58, 0x38, 0x01, 0x00, 0x04, 0x22, 0x01, 0x01, 0x31, 0x0E,
-       0x06, 0x15, 0x21, 0x01, 0x00, 0x58, 0x38, 0x22, 0x01, 0x80, 0x64, 0x0E,
-       0x06, 0x05, 0x01, 0x82, 0x00, 0x08, 0x23, 0x46, 0x00, 0x04, 0x07, 0x21,
-       0x01, 0x82, 0x00, 0x08, 0x23, 0x21, 0x00, 0x00, 0x01, 0x00, 0x28, 0x06,
-       0x06, 0x33, 0x81, 0x08, 0x30, 0x04, 0x77, 0x22, 0x06, 0x04, 0x01, 0x01,
-       0x71, 0x38, 0x00, 0x00, 0x28, 0x06, 0x0B, 0x69, 0x27, 0x01, 0x14, 0x0D,
-       0x06, 0x02, 0x56, 0x23, 0x04, 0x12, 0x81, 0x25, 0x01, 0x07, 0x12, 0x22,
-       0x01, 0x02, 0x0D, 0x06, 0x06, 0x06, 0x02, 0x56, 0x23, 0x04, 0x6F, 0x21,
-       0x81, 0x1A, 0x01, 0x01, 0x0D, 0x2C, 0x30, 0x06, 0x02, 0x4C, 0x23, 0x22,
-       0x01, 0x01, 0x81, 0x20, 0x2F, 0x81, 0x0D, 0x00, 0x0A, 0x81, 0x12, 0x01,
-       0x01, 0x0E, 0x05, 0x02, 0x56, 0x23, 0x81, 0x17, 0x22, 0x03, 0x00, 0x5B,
-       0x36, 0x5C, 0x01, 0x20, 0x81, 0x0E, 0x81, 0x19, 0x22, 0x01, 0x20, 0x0F,
-       0x06, 0x02, 0x55, 0x23, 0x22, 0x70, 0x38, 0x6F, 0x3B, 0x81, 0x0E, 0x17,
-       0x03, 0x01, 0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x03, 0x02, 0x01, 0x00,
-       0x03, 0x03, 0x65, 0x81, 0x02, 0x14, 0x31, 0x08, 0x03, 0x04, 0x03, 0x05,
-       0x22, 0x06, 0x80, 0x70, 0x81, 0x17, 0x22, 0x03, 0x06, 0x02, 0x01, 0x06,
-       0x0A, 0x22, 0x5A, 0x25, 0x0E, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x03, 0x22,
-       0x01, 0x81, 0x7F, 0x0E, 0x06, 0x0A, 0x6B, 0x27, 0x06, 0x02, 0x51, 0x23,
-       0x01, 0x7F, 0x03, 0x02, 0x22, 0x01, 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x11,
-       0x02, 0x00, 0x78, 0x25, 0x10, 0x02, 0x00, 0x77, 0x25, 0x0A, 0x12, 0x06,
-       0x04, 0x01, 0x7F, 0x03, 0x00, 0x81, 0x1B, 0x22, 0x44, 0x06, 0x03, 0x21,
-       0x04, 0x27, 0x01, 0x00, 0x81, 0x04, 0x06, 0x0B, 0x01, 0x02, 0x0B, 0x5D,
-       0x08, 0x02, 0x06, 0x3B, 0x36, 0x04, 0x16, 0x21, 0x02, 0x05, 0x02, 0x04,
-       0x10, 0x06, 0x02, 0x4F, 0x23, 0x02, 0x06, 0x02, 0x05, 0x36, 0x02, 0x05,
-       0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x0C, 0x21, 0x01, 0x00, 0x03,
-       0x07, 0x81, 0x19, 0x81, 0x06, 0x22, 0x06, 0x0A, 0x81, 0x19, 0x05, 0x04,
-       0x01, 0x7F, 0x03, 0x07, 0x04, 0x73, 0x7D, 0x01, 0x00, 0x6D, 0x38, 0x01,
-       0x88, 0x04, 0x64, 0x36, 0x01, 0x84, 0x80, 0x80, 0x00, 0x60, 0x37, 0x22,
-       0x06, 0x80, 0x4D, 0x81, 0x17, 0x81, 0x06, 0x22, 0x06, 0x80, 0x44, 0x81,
-       0x17, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x11, 0x04, 0x34,
-       0x01, 0x01, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x0F, 0x04, 0x29, 0x01,
-       0x83, 0xFE, 0x01, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x10, 0x04, 0x1C,
-       0x01, 0x0D, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x15, 0x04, 0x11, 0x01,
-       0x0A, 0x31, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x16, 0x04, 0x06, 0x21, 0x81,
-       0x14, 0x01, 0x00, 0x21, 0x04, 0xFF, 0x38, 0x7D, 0x7D, 0x02, 0x01, 0x02,
-       0x03, 0x12, 0x03, 0x01, 0x02, 0x00, 0x44, 0x06, 0x09, 0x5B, 0x25, 0x79,
-       0x36, 0x01, 0x80, 0x56, 0x81, 0x03, 0x77, 0x25, 0x22, 0x02, 0x00, 0x0F,
-       0x06, 0x03, 0x21, 0x02, 0x00, 0x22, 0x01, 0x86, 0x00, 0x0A, 0x06, 0x02,
-       0x52, 0x23, 0x02, 0x00, 0x78, 0x25, 0x0A, 0x06, 0x05, 0x01, 0x80, 0x46,
-       0x81, 0x03, 0x02, 0x01, 0x06, 0x10, 0x75, 0x25, 0x02, 0x00, 0x0C, 0x06,
-       0x05, 0x21, 0x75, 0x25, 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x22, 0x75,
-       0x36, 0x22, 0x76, 0x36, 0x22, 0x79, 0x36, 0x01, 0x86, 0x03, 0x10, 0x03,
-       0x08, 0x02, 0x02, 0x06, 0x04, 0x01, 0x02, 0x6B, 0x38, 0x02, 0x07, 0x05,
-       0x04, 0x01, 0x28, 0x81, 0x03, 0x3A, 0x21, 0x01, 0x82, 0x01, 0x07, 0x64,
-       0x25, 0x12, 0x22, 0x64, 0x36, 0x45, 0x03, 0x09, 0x60, 0x26, 0x39, 0x12,
-       0x22, 0x60, 0x37, 0x05, 0x04, 0x01, 0x00, 0x03, 0x09, 0x02, 0x01, 0x06,
-       0x03, 0x01, 0x7F, 0x00, 0x6F, 0x01, 0x20, 0x2B, 0x01, 0x20, 0x70, 0x38,
-       0x5D, 0x22, 0x03, 0x05, 0x22, 0x02, 0x04, 0x0A, 0x06, 0x80, 0x47, 0x22,
-       0x25, 0x22, 0x7C, 0x02, 0x09, 0x05, 0x13, 0x22, 0x01, 0x0C, 0x11, 0x22,
-       0x01, 0x01, 0x0E, 0x3B, 0x01, 0x02, 0x0E, 0x30, 0x06, 0x04, 0x4B, 0x01,
-       0x00, 0x22, 0x02, 0x08, 0x05, 0x0E, 0x22, 0x01, 0x81, 0x70, 0x12, 0x01,
-       0x20, 0x0D, 0x06, 0x04, 0x4B, 0x01, 0x00, 0x22, 0x22, 0x06, 0x10, 0x02,
-       0x05, 0x4A, 0x36, 0x02, 0x05, 0x36, 0x02, 0x05, 0x01, 0x04, 0x08, 0x03,
-       0x05, 0x04, 0x01, 0x4B, 0x01, 0x04, 0x08, 0x04, 0xFF, 0x32, 0x21, 0x02,
-       0x05, 0x5D, 0x09, 0x01, 0x02, 0x11, 0x22, 0x05, 0x04, 0x01, 0x28, 0x81,
-       0x03, 0x5E, 0x38, 0x15, 0x05, 0x04, 0x01, 0x28, 0x81, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x81, 0x12, 0x01, 0x10, 0x0E, 0x05, 0x02, 0x56, 0x23, 0x5A,
-       0x25, 0x81, 0x24, 0x06, 0x19, 0x81, 0x17, 0x22, 0x01, 0x84, 0x00, 0x0F,
-       0x06, 0x02, 0x53, 0x23, 0x22, 0x03, 0x00, 0x67, 0x3B, 0x81, 0x0E, 0x02,
-       0x00, 0x5A, 0x25, 0x81, 0x07, 0x20, 0x5A, 0x25, 0x22, 0x81, 0x22, 0x3B,
-       0x81, 0x21, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x30, 0x06,
-       0x17, 0x81, 0x19, 0x22, 0x03, 0x03, 0x67, 0x3B, 0x81, 0x0E, 0x02, 0x03,
-       0x5A, 0x25, 0x81, 0x07, 0x02, 0x02, 0x06, 0x03, 0x1F, 0x04, 0x01, 0x1D,
-       0x7D, 0x00, 0x00, 0x7E, 0x81, 0x12, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x56,
-       0x23, 0x67, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x81, 0x0E, 0x7D, 0x67, 0x22,
-       0x01, 0x0C, 0x08, 0x01, 0x0C, 0x29, 0x05, 0x02, 0x4D, 0x23, 0x00, 0x02,
-       0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x7A, 0x02, 0x01, 0x02, 0x00, 0x32,
-       0x22, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x4B, 0x00, 0x81, 0x27, 0x04, 0x73,
-       0x00, 0x81, 0x17, 0x01, 0x01, 0x0D, 0x06, 0x02, 0x4E, 0x23, 0x81, 0x19,
-       0x22, 0x22, 0x46, 0x3B, 0x01, 0x05, 0x10, 0x30, 0x06, 0x02, 0x4E, 0x23,
-       0x01, 0x08, 0x08, 0x22, 0x66, 0x27, 0x0A, 0x06, 0x0D, 0x22, 0x01, 0x01,
-       0x3B, 0x0B, 0x35, 0x22, 0x66, 0x38, 0x68, 0x38, 0x04, 0x01, 0x21, 0x00,
-       0x00, 0x81, 0x17, 0x6B, 0x27, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x14, 0x21,
-       0x01, 0x01, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x81, 0x19, 0x06, 0x02, 0x51,
-       0x23, 0x01, 0x02, 0x6B, 0x38, 0x04, 0x2A, 0x01, 0x02, 0x31, 0x0E, 0x06,
-       0x21, 0x21, 0x01, 0x0D, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x81, 0x19, 0x01,
-       0x0C, 0x0E, 0x05, 0x02, 0x51, 0x23, 0x67, 0x01, 0x0C, 0x81, 0x0E, 0x6C,
-       0x67, 0x01, 0x0C, 0x29, 0x05, 0x02, 0x51, 0x23, 0x04, 0x03, 0x51, 0x23,
-       0x21, 0x00, 0x00, 0x81, 0x17, 0x81, 0x06, 0x81, 0x17, 0x81, 0x06, 0x22,
-       0x06, 0x22, 0x81, 0x19, 0x06, 0x04, 0x81, 0x14, 0x04, 0x18, 0x81, 0x17,
-       0x22, 0x01, 0x81, 0x7F, 0x0C, 0x06, 0x0D, 0x22, 0x6D, 0x08, 0x01, 0x00,
-       0x3B, 0x38, 0x6D, 0x3B, 0x81, 0x0E, 0x04, 0x02, 0x81, 0x1F, 0x04, 0x5B,
-       0x7D, 0x7D, 0x00, 0x00, 0x81, 0x13, 0x22, 0x46, 0x06, 0x07, 0x21, 0x06,
-       0x02, 0x4F, 0x23, 0x04, 0x73, 0x00, 0x00, 0x81, 0x1A, 0x01, 0x03, 0x81,
-       0x18, 0x3B, 0x21, 0x3B, 0x00, 0x00, 0x81, 0x17, 0x81, 0x1F, 0x00, 0x02,
-       0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x64, 0x36, 0x81, 0x17, 0x81, 0x06,
-       0x22, 0x06, 0x34, 0x81, 0x19, 0x03, 0x00, 0x81, 0x19, 0x03, 0x01, 0x02,
-       0x00, 0x01, 0x02, 0x10, 0x02, 0x00, 0x01, 0x06, 0x0C, 0x12, 0x02, 0x01,
-       0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x03, 0x0E, 0x30, 0x12, 0x06, 0x11,
-       0x64, 0x25, 0x01, 0x01, 0x02, 0x01, 0x49, 0x01, 0x02, 0x0B, 0x02, 0x00,
-       0x08, 0x0B, 0x30, 0x64, 0x36, 0x04, 0x49, 0x7D, 0x7D, 0x00, 0x00, 0x81,
-       0x17, 0x81, 0x06, 0x81, 0x17, 0x81, 0x06, 0x01, 0x00, 0x60, 0x37, 0x22,
-       0x06, 0x16, 0x81, 0x17, 0x22, 0x01, 0x20, 0x0A, 0x06, 0x0B, 0x01, 0x01,
-       0x3B, 0x0B, 0x60, 0x26, 0x30, 0x60, 0x37, 0x04, 0x01, 0x21, 0x04, 0x67,
-       0x7D, 0x7D, 0x00, 0x00, 0x01, 0x02, 0x7A, 0x81, 0x1A, 0x01, 0x08, 0x0B,
-       0x81, 0x1A, 0x08, 0x00, 0x00, 0x01, 0x03, 0x7A, 0x81, 0x1A, 0x01, 0x08,
-       0x0B, 0x81, 0x1A, 0x08, 0x01, 0x08, 0x0B, 0x81, 0x1A, 0x08, 0x00, 0x00,
-       0x01, 0x01, 0x7A, 0x81, 0x1A, 0x00, 0x00, 0x33, 0x22, 0x44, 0x05, 0x01,
-       0x00, 0x21, 0x81, 0x27, 0x04, 0x75, 0x02, 0x03, 0x00, 0x74, 0x27, 0x03,
-       0x01, 0x01, 0x00, 0x22, 0x02, 0x01, 0x0A, 0x06, 0x10, 0x22, 0x01, 0x01,
-       0x0B, 0x73, 0x08, 0x25, 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00, 0x48, 0x04,
-       0x6A, 0x21, 0x01, 0x7F, 0x00, 0x00, 0x24, 0x16, 0x2F, 0x06, 0x05, 0x81,
-       0x25, 0x21, 0x04, 0x77, 0x01, 0x16, 0x6A, 0x38, 0x01, 0x00, 0x81, 0x33,
-       0x01, 0x00, 0x81, 0x32, 0x24, 0x01, 0x17, 0x6A, 0x38, 0x00, 0x00, 0x01,
-       0x15, 0x6A, 0x38, 0x3B, 0x43, 0x21, 0x43, 0x21, 0x24, 0x00, 0x00, 0x01,
-       0x01, 0x3B, 0x81, 0x1D, 0x00, 0x00, 0x3B, 0x31, 0x7A, 0x3B, 0x22, 0x06,
-       0x06, 0x81, 0x1A, 0x21, 0x49, 0x04, 0x77, 0x21, 0x00, 0x02, 0x03, 0x00,
-       0x5A, 0x25, 0x7C, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x12, 0x02, 0x01,
-       0x01, 0x04, 0x11, 0x01, 0x0F, 0x12, 0x02, 0x01, 0x01, 0x08, 0x11, 0x01,
-       0x0F, 0x12, 0x01, 0x00, 0x31, 0x0E, 0x06, 0x10, 0x21, 0x01, 0x00, 0x01,
-       0x18, 0x02, 0x00, 0x06, 0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x80, 0x56,
-       0x01, 0x01, 0x31, 0x0E, 0x06, 0x10, 0x21, 0x01, 0x01, 0x01, 0x10, 0x02,
-       0x00, 0x06, 0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x80, 0x40, 0x01, 0x02,
-       0x31, 0x0E, 0x06, 0x0F, 0x21, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, 0x06,
-       0x03, 0x3E, 0x04, 0x01, 0x3F, 0x04, 0x2B, 0x01, 0x03, 0x31, 0x0E, 0x06,
-       0x0E, 0x21, 0x21, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x3C, 0x04, 0x01,
-       0x3D, 0x04, 0x17, 0x01, 0x04, 0x31, 0x0E, 0x06, 0x0E, 0x21, 0x21, 0x01,
-       0x20, 0x02, 0x00, 0x06, 0x03, 0x3C, 0x04, 0x01, 0x3D, 0x04, 0x03, 0x50,
-       0x23, 0x21, 0x00, 0x00, 0x7C, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00,
-       0x00, 0x7C, 0x01, 0x0C, 0x11, 0x22, 0x47, 0x3B, 0x01, 0x03, 0x0A, 0x12,
-       0x00, 0x00, 0x7C, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x7C,
-       0x01, 0x0C, 0x11, 0x46, 0x00, 0x00, 0x18, 0x01, 0x00, 0x57, 0x27, 0x22,
-       0x06, 0x20, 0x01, 0x01, 0x31, 0x0E, 0x06, 0x07, 0x21, 0x01, 0x00, 0x81,
-       0x00, 0x04, 0x11, 0x01, 0x02, 0x31, 0x0E, 0x06, 0x0A, 0x21, 0x59, 0x27,
-       0x06, 0x03, 0x01, 0x10, 0x30, 0x04, 0x01, 0x21, 0x04, 0x01, 0x21, 0x5F,
-       0x27, 0x05, 0x35, 0x28, 0x06, 0x32, 0x69, 0x27, 0x01, 0x14, 0x31, 0x0E,
-       0x06, 0x06, 0x21, 0x01, 0x02, 0x30, 0x04, 0x24, 0x01, 0x15, 0x31, 0x0E,
-       0x06, 0x0B, 0x21, 0x81, 0x09, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x00, 0x04,
-       0x13, 0x01, 0x16, 0x31, 0x0E, 0x06, 0x06, 0x21, 0x01, 0x01, 0x30, 0x04,
-       0x07, 0x21, 0x01, 0x04, 0x30, 0x01, 0x00, 0x21, 0x16, 0x06, 0x03, 0x01,
-       0x08, 0x30, 0x00, 0x00, 0x18, 0x22, 0x05, 0x10, 0x28, 0x06, 0x0D, 0x69,
-       0x27, 0x01, 0x15, 0x0E, 0x06, 0x05, 0x21, 0x81, 0x09, 0x04, 0x01, 0x1C,
-       0x00, 0x00, 0x81, 0x25, 0x01, 0x07, 0x12, 0x01, 0x01, 0x0F, 0x06, 0x02,
-       0x56, 0x23, 0x00, 0x01, 0x03, 0x00, 0x24, 0x16, 0x06, 0x05, 0x02, 0x00,
-       0x6A, 0x38, 0x00, 0x81, 0x25, 0x21, 0x04, 0x73, 0x00, 0x01, 0x14, 0x81,
-       0x28, 0x01, 0x01, 0x81, 0x33, 0x24, 0x22, 0x01, 0x00, 0x81, 0x20, 0x01,
-       0x16, 0x81, 0x28, 0x81, 0x2B, 0x24, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x33,
-       0x40, 0x22, 0x01, 0x03, 0x08, 0x81, 0x32, 0x81, 0x32, 0x13, 0x22, 0x44,
-       0x06, 0x02, 0x21, 0x00, 0x81, 0x32, 0x1A, 0x22, 0x06, 0x06, 0x67, 0x3B,
-       0x81, 0x2F, 0x04, 0x76, 0x21, 0x04, 0x6A, 0x00, 0x7E, 0x01, 0x14, 0x81,
-       0x33, 0x01, 0x0C, 0x81, 0x32, 0x67, 0x01, 0x0C, 0x81, 0x2F, 0x00, 0x03,
-       0x03, 0x00, 0x01, 0x02, 0x81, 0x33, 0x01, 0x80, 0x46, 0x6B, 0x27, 0x01,
-       0x02, 0x0E, 0x06, 0x0C, 0x02, 0x00, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02,
-       0x01, 0x1D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x01, 0x68, 0x27, 0x06, 0x04,
-       0x01, 0x05, 0x04, 0x02, 0x01, 0x00, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02,
-       0x08, 0x22, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08, 0x81, 0x32, 0x75, 0x25,
-       0x81, 0x31, 0x6E, 0x01, 0x04, 0x14, 0x6E, 0x01, 0x04, 0x08, 0x01, 0x1C,
-       0x2B, 0x6E, 0x01, 0x20, 0x81, 0x2F, 0x01, 0x20, 0x81, 0x33, 0x6F, 0x01,
-       0x20, 0x81, 0x2F, 0x5A, 0x25, 0x81, 0x31, 0x01, 0x00, 0x81, 0x33, 0x02,
-       0x01, 0x02, 0x02, 0x08, 0x22, 0x06, 0x30, 0x81, 0x31, 0x02, 0x01, 0x22,
-       0x06, 0x13, 0x01, 0x83, 0xFE, 0x01, 0x81, 0x31, 0x01, 0x04, 0x09, 0x22,
-       0x81, 0x31, 0x49, 0x6C, 0x3B, 0x81, 0x30, 0x04, 0x01, 0x21, 0x02, 0x02,
-       0x06, 0x0F, 0x01, 0x01, 0x81, 0x31, 0x01, 0x01, 0x81, 0x31, 0x68, 0x27,
-       0x01, 0x08, 0x09, 0x81, 0x33, 0x04, 0x01, 0x21, 0x00, 0x00, 0x01, 0x0E,
-       0x81, 0x33, 0x01, 0x00, 0x81, 0x32, 0x00, 0x03, 0x5A, 0x25, 0x81, 0x22,
-       0x05, 0x01, 0x00, 0x60, 0x26, 0x01, 0x00, 0x81, 0x02, 0x11, 0x01, 0x01,
-       0x12, 0x46, 0x06, 0x03, 0x48, 0x04, 0x74, 0x03, 0x00, 0x21, 0x02, 0x00,
-       0x1E, 0x22, 0x44, 0x06, 0x02, 0x2E, 0x23, 0x03, 0x01, 0x75, 0x25, 0x01,
-       0x86, 0x03, 0x10, 0x03, 0x02, 0x01, 0x0C, 0x81, 0x33, 0x02, 0x01, 0x62,
-       0x27, 0x08, 0x02, 0x02, 0x01, 0x02, 0x12, 0x08, 0x01, 0x06, 0x08, 0x81,
-       0x32, 0x01, 0x03, 0x81, 0x33, 0x02, 0x00, 0x81, 0x31, 0x61, 0x62, 0x27,
-       0x81, 0x30, 0x02, 0x02, 0x06, 0x10, 0x72, 0x27, 0x81, 0x33, 0x5A, 0x25,
-       0x81, 0x23, 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x81, 0x33, 0x02, 0x01,
-       0x81, 0x31, 0x67, 0x02, 0x01, 0x81, 0x2F, 0x00, 0x00, 0x42, 0x22, 0x01,
-       0x00, 0x0E, 0x06, 0x02, 0x4B, 0x00, 0x81, 0x25, 0x21, 0x04, 0x72, 0x00,
-       0x22, 0x81, 0x33, 0x81, 0x2F, 0x00, 0x00, 0x22, 0x01, 0x08, 0x41, 0x81,
-       0x33, 0x81, 0x33, 0x00, 0x00, 0x22, 0x01, 0x10, 0x41, 0x81, 0x33, 0x81,
-       0x31, 0x00, 0x00, 0x22, 0x43, 0x06, 0x02, 0x21, 0x00, 0x81, 0x25, 0x21,
-       0x04, 0x75
+       0x00, 0x00, 0x09, 0x29, 0x56, 0x06, 0x02, 0x62, 0x2A, 0x00, 0x00, 0x01,
+       0x01, 0x00, 0x01, 0x03, 0x00, 0x81, 0x11, 0x29, 0x5C, 0x46, 0x81, 0x15,
+       0x29, 0x05, 0x04, 0x5D, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0F, 0x06, 0x03,
+       0x81, 0x15, 0x00, 0x5C, 0x04, 0x69, 0x00, 0x06, 0x02, 0x62, 0x2A, 0x00,
+       0x00, 0x29, 0x81, 0x02, 0x46, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x46, 0x70,
+       0x2D, 0x81, 0x1D, 0x1C, 0x7D, 0x01, 0x0C, 0x32, 0x00, 0x00, 0x29, 0x21,
+       0x01, 0x08, 0x0C, 0x46, 0x5A, 0x21, 0x08, 0x00, 0x01, 0x03, 0x00, 0x01,
+       0x00, 0x6F, 0x41, 0x2B, 0x19, 0x37, 0x06, 0x08, 0x02, 0x00, 0x81, 0x43,
+       0x03, 0x00, 0x04, 0x74, 0x01, 0x00, 0x81, 0x3B, 0x02, 0x00, 0x29, 0x19,
+       0x13, 0x06, 0x02, 0x69, 0x2A, 0x81, 0x43, 0x04, 0x75, 0x00, 0x01, 0x00,
+       0x6F, 0x41, 0x01, 0x16, 0x81, 0x00, 0x41, 0x35, 0x81, 0x25, 0x34, 0x06,
+       0x02, 0x6B, 0x2A, 0x06, 0x0D, 0x81, 0x4A, 0x01, 0x00, 0x81, 0x46, 0x01,
+       0x00, 0x81, 0x21, 0x04, 0x80, 0x59, 0x81, 0x4A, 0x81, 0x47, 0x28, 0x81,
+       0x4C, 0x4B, 0x06, 0x02, 0x81, 0x48, 0x81, 0x4B, 0x2B, 0x4B, 0x06, 0x3C,
+       0x01, 0x00, 0x81, 0x22, 0x29, 0x56, 0x06, 0x13, 0x01, 0x02, 0x81, 0x1A,
+       0x05, 0x02, 0x36, 0x2A, 0x28, 0x81, 0x26, 0x81, 0x24, 0x29, 0x81, 0x3C,
+       0x28, 0x04, 0x1F, 0x29, 0x58, 0x06, 0x0D, 0x28, 0x01, 0x02, 0x81, 0x1A,
+       0x05, 0x02, 0x68, 0x2A, 0x81, 0x26, 0x04, 0x0E, 0x81, 0x28, 0x29, 0x05,
+       0x05, 0x28, 0x81, 0x20, 0x04, 0x04, 0x81, 0x27, 0x81, 0x23, 0x04, 0x02,
+       0x81, 0x26, 0x01, 0x00, 0x81, 0x21, 0x01, 0x00, 0x81, 0x46, 0x3D, 0x01,
+       0x01, 0x6F, 0x41, 0x01, 0x17, 0x81, 0x00, 0x41, 0x00, 0x00, 0x39, 0x39,
+       0x00, 0x01, 0x03, 0x00, 0x2B, 0x19, 0x37, 0x06, 0x05, 0x81, 0x42, 0x28,
+       0x04, 0x77, 0x01, 0x02, 0x02, 0x00, 0x81, 0x3A, 0x19, 0x37, 0x06, 0x05,
+       0x81, 0x42, 0x28, 0x04, 0x77, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x2A,
+       0x00, 0x00, 0x79, 0x2E, 0x46, 0x12, 0x01, 0x01, 0x13, 0x36, 0x00, 0x00,
+       0x01, 0x7F, 0x81, 0x17, 0x81, 0x42, 0x29, 0x01, 0x07, 0x13, 0x01, 0x00,
+       0x39, 0x0F, 0x06, 0x0A, 0x28, 0x01, 0x10, 0x13, 0x06, 0x02, 0x81, 0x39,
+       0x04, 0x2F, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x26, 0x28, 0x28, 0x81, 0x01,
+       0x2F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x81, 0x1A, 0x38, 0x06, 0x11, 0x2B,
+       0x19, 0x37, 0x06, 0x05, 0x81, 0x42, 0x28, 0x04, 0x77, 0x01, 0x80, 0x64,
+       0x81, 0x3B, 0x04, 0x04, 0x01, 0x00, 0x81, 0x17, 0x04, 0x03, 0x6B, 0x2A,
+       0x28, 0x04, 0xFF, 0x38, 0x01, 0x29, 0x03, 0x00, 0x09, 0x29, 0x56, 0x06,
+       0x02, 0x62, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0F, 0x13,
+       0x00, 0x00, 0x6E, 0x2F, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x10, 0x28, 0x29,
+       0x01, 0x01, 0x0E, 0x06, 0x03, 0x28, 0x01, 0x02, 0x6E, 0x41, 0x01, 0x00,
+       0x04, 0x22, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x15, 0x28, 0x01, 0x00, 0x6E,
+       0x41, 0x29, 0x01, 0x80, 0x64, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x08,
+       0x2A, 0x58, 0x00, 0x04, 0x07, 0x28, 0x01, 0x82, 0x00, 0x08, 0x2A, 0x28,
+       0x00, 0x00, 0x01, 0x00, 0x30, 0x06, 0x06, 0x3C, 0x81, 0x1E, 0x38, 0x04,
+       0x77, 0x29, 0x06, 0x05, 0x01, 0x01, 0x81, 0x07, 0x41, 0x00, 0x00, 0x01,
+       0x1F, 0x13, 0x01, 0x12, 0x0F, 0x05, 0x02, 0x6C, 0x2A, 0x70, 0x2D, 0x29,
+       0x81, 0x3E, 0x05, 0x02, 0x6B, 0x2A, 0x81, 0x1D, 0x27, 0x00, 0x00, 0x30,
+       0x06, 0x0B, 0x7F, 0x2F, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x6B, 0x2A, 0x04,
+       0x12, 0x81, 0x42, 0x01, 0x07, 0x13, 0x29, 0x01, 0x02, 0x0E, 0x06, 0x06,
+       0x06, 0x02, 0x6B, 0x2A, 0x04, 0x6F, 0x28, 0x81, 0x37, 0x01, 0x01, 0x0E,
+       0x34, 0x38, 0x06, 0x02, 0x5E, 0x2A, 0x29, 0x01, 0x01, 0x81, 0x3D, 0x37,
+       0x81, 0x29, 0x00, 0x01, 0x81, 0x2E, 0x01, 0x0B, 0x0F, 0x05, 0x02, 0x6B,
+       0x2A, 0x29, 0x01, 0x03, 0x0F, 0x06, 0x09, 0x81, 0x35, 0x06, 0x02, 0x62,
+       0x2A, 0x46, 0x28, 0x00, 0x46, 0x55, 0x81, 0x35, 0x81, 0x1C, 0x29, 0x06,
+       0x27, 0x81, 0x35, 0x81, 0x1C, 0x29, 0x54, 0x29, 0x06, 0x19, 0x29, 0x01,
+       0x82, 0x00, 0x10, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x29, 0x03,
+       0x00, 0x7D, 0x02, 0x00, 0x81, 0x2A, 0x02, 0x00, 0x51, 0x04, 0x64, 0x81,
+       0x13, 0x52, 0x04, 0x56, 0x81, 0x13, 0x81, 0x13, 0x53, 0x29, 0x06, 0x02,
+       0x36, 0x00, 0x28, 0x2C, 0x00, 0x02, 0x29, 0x01, 0x20, 0x13, 0x05, 0x02,
+       0x6C, 0x2A, 0x01, 0x0F, 0x13, 0x03, 0x00, 0x81, 0x24, 0x81, 0x0B, 0x2D,
+       0x01, 0x86, 0x03, 0x11, 0x06, 0x24, 0x81, 0x34, 0x29, 0x01, 0x81, 0x7F,
+       0x13, 0x5A, 0x01, 0x01, 0x12, 0x02, 0x00, 0x0F, 0x05, 0x02, 0x64, 0x2A,
+       0x01, 0x08, 0x12, 0x29, 0x01, 0x02, 0x0B, 0x39, 0x01, 0x06, 0x10, 0x38,
+       0x06, 0x02, 0x66, 0x2A, 0x04, 0x0D, 0x02, 0x00, 0x01, 0x01, 0x0F, 0x06,
+       0x04, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x20, 0x05, 0x02, 0x66, 0x2A,
+       0x81, 0x34, 0x29, 0x03, 0x01, 0x29, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02,
+       0x67, 0x2A, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x01, 0x4E, 0x29, 0x06, 0x01,
+       0x2A, 0x28, 0x81, 0x13, 0x00, 0x00, 0x1D, 0x81, 0x2E, 0x01, 0x0F, 0x0F,
+       0x05, 0x02, 0x6B, 0x2A, 0x00, 0x0A, 0x81, 0x2E, 0x01, 0x01, 0x0F, 0x05,
+       0x02, 0x6B, 0x2A, 0x81, 0x34, 0x29, 0x03, 0x00, 0x71, 0x3F, 0x72, 0x01,
+       0x20, 0x81, 0x2A, 0x81, 0x36, 0x29, 0x01, 0x20, 0x10, 0x06, 0x02, 0x6A,
+       0x2A, 0x29, 0x81, 0x06, 0x41, 0x81, 0x05, 0x46, 0x81, 0x2A, 0x1A, 0x03,
+       0x01, 0x81, 0x34, 0x81, 0x1C, 0x01, 0x00, 0x03, 0x02, 0x01, 0x00, 0x03,
+       0x03, 0x7B, 0x81, 0x18, 0x17, 0x39, 0x08, 0x03, 0x04, 0x03, 0x05, 0x29,
+       0x06, 0x80, 0x73, 0x81, 0x34, 0x29, 0x03, 0x06, 0x02, 0x01, 0x06, 0x0A,
+       0x29, 0x70, 0x2D, 0x0F, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x03, 0x29, 0x01,
+       0x81, 0x7F, 0x0F, 0x06, 0x0B, 0x81, 0x01, 0x2F, 0x06, 0x02, 0x63, 0x2A,
+       0x01, 0x7F, 0x03, 0x02, 0x29, 0x01, 0x81, 0xAC, 0x00, 0x0F, 0x06, 0x13,
+       0x02, 0x00, 0x81, 0x0E, 0x2D, 0x11, 0x02, 0x00, 0x81, 0x0D, 0x2D, 0x0B,
+       0x13, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x81, 0x38, 0x29, 0x56, 0x06,
+       0x03, 0x28, 0x04, 0x27, 0x01, 0x00, 0x81, 0x1A, 0x06, 0x0B, 0x01, 0x02,
+       0x0C, 0x73, 0x08, 0x02, 0x06, 0x46, 0x3F, 0x04, 0x16, 0x28, 0x02, 0x05,
+       0x02, 0x04, 0x11, 0x06, 0x02, 0x61, 0x2A, 0x02, 0x06, 0x02, 0x05, 0x3F,
+       0x02, 0x05, 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x09, 0x28, 0x01,
+       0x00, 0x03, 0x07, 0x81, 0x36, 0x81, 0x1C, 0x29, 0x06, 0x0A, 0x81, 0x36,
+       0x05, 0x04, 0x01, 0x7F, 0x03, 0x07, 0x04, 0x73, 0x81, 0x13, 0x01, 0x00,
+       0x81, 0x03, 0x41, 0x01, 0x88, 0x04, 0x7A, 0x3F, 0x01, 0x84, 0x80, 0x80,
+       0x00, 0x76, 0x40, 0x29, 0x06, 0x80, 0x4E, 0x81, 0x34, 0x81, 0x1C, 0x29,
+       0x06, 0x80, 0x44, 0x81, 0x34, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x05, 0x28,
+       0x81, 0x2D, 0x04, 0x34, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81,
+       0x2B, 0x04, 0x29, 0x01, 0x83, 0xFE, 0x01, 0x39, 0x0F, 0x06, 0x05, 0x28,
+       0x81, 0x2C, 0x04, 0x1C, 0x01, 0x0D, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81,
+       0x32, 0x04, 0x11, 0x01, 0x0A, 0x39, 0x0F, 0x06, 0x05, 0x28, 0x81, 0x33,
+       0x04, 0x06, 0x28, 0x81, 0x30, 0x01, 0x00, 0x28, 0x04, 0xFF, 0x38, 0x81,
+       0x13, 0x81, 0x13, 0x02, 0x01, 0x02, 0x03, 0x13, 0x03, 0x01, 0x02, 0x00,
+       0x56, 0x06, 0x0A, 0x71, 0x2D, 0x81, 0x0F, 0x3F, 0x01, 0x80, 0x56, 0x81,
+       0x19, 0x81, 0x0D, 0x2D, 0x29, 0x02, 0x00, 0x10, 0x06, 0x03, 0x28, 0x02,
+       0x00, 0x29, 0x01, 0x86, 0x00, 0x0B, 0x06, 0x02, 0x65, 0x2A, 0x02, 0x00,
+       0x81, 0x0E, 0x2D, 0x0B, 0x06, 0x05, 0x01, 0x80, 0x46, 0x81, 0x19, 0x02,
+       0x01, 0x06, 0x12, 0x81, 0x0B, 0x2D, 0x02, 0x00, 0x0D, 0x06, 0x06, 0x28,
+       0x81, 0x0B, 0x2D, 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x29, 0x81, 0x0B,
+       0x3F, 0x29, 0x81, 0x0C, 0x3F, 0x29, 0x81, 0x0F, 0x3F, 0x01, 0x86, 0x03,
+       0x11, 0x03, 0x08, 0x02, 0x02, 0x06, 0x05, 0x01, 0x02, 0x81, 0x01, 0x41,
+       0x02, 0x07, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19, 0x43, 0x28, 0x01, 0x82,
+       0x01, 0x07, 0x7A, 0x2D, 0x13, 0x29, 0x7A, 0x3F, 0x29, 0x01, 0x81, 0x7F,
+       0x13, 0x57, 0x36, 0x46, 0x01, 0x08, 0x12, 0x57, 0x01, 0x02, 0x13, 0x38,
+       0x03, 0x09, 0x76, 0x2E, 0x42, 0x13, 0x29, 0x76, 0x40, 0x05, 0x04, 0x01,
+       0x00, 0x03, 0x09, 0x02, 0x01, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x81, 0x05,
+       0x01, 0x20, 0x33, 0x01, 0x20, 0x81, 0x06, 0x41, 0x73, 0x29, 0x03, 0x05,
+       0x29, 0x02, 0x04, 0x0B, 0x06, 0x80, 0x4A, 0x29, 0x2D, 0x29, 0x81, 0x12,
+       0x29, 0x01, 0x0C, 0x12, 0x29, 0x01, 0x01, 0x0F, 0x46, 0x01, 0x02, 0x0F,
+       0x38, 0x06, 0x0A, 0x29, 0x02, 0x09, 0x13, 0x05, 0x04, 0x5D, 0x01, 0x00,
+       0x29, 0x02, 0x08, 0x05, 0x0E, 0x29, 0x01, 0x81, 0x70, 0x13, 0x01, 0x20,
+       0x0E, 0x06, 0x04, 0x5D, 0x01, 0x00, 0x29, 0x29, 0x06, 0x10, 0x02, 0x05,
+       0x5C, 0x3F, 0x02, 0x05, 0x3F, 0x02, 0x05, 0x01, 0x04, 0x08, 0x03, 0x05,
+       0x04, 0x01, 0x5D, 0x01, 0x04, 0x08, 0x04, 0xFF, 0x2F, 0x28, 0x02, 0x05,
+       0x73, 0x09, 0x01, 0x02, 0x12, 0x29, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19,
+       0x74, 0x41, 0x18, 0x05, 0x04, 0x01, 0x28, 0x81, 0x19, 0x01, 0x00, 0x00,
+       0x00, 0x81, 0x28, 0x81, 0x27, 0x00, 0x04, 0x70, 0x2D, 0x81, 0x41, 0x06,
+       0x19, 0x81, 0x34, 0x29, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02, 0x67, 0x2A,
+       0x29, 0x03, 0x00, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x00, 0x70, 0x2D, 0x81,
+       0x1D, 0x26, 0x70, 0x2D, 0x29, 0x81, 0x3F, 0x46, 0x81, 0x3E, 0x03, 0x01,
+       0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x38, 0x06, 0x17, 0x81, 0x36, 0x29,
+       0x03, 0x03, 0x7D, 0x46, 0x81, 0x2A, 0x02, 0x03, 0x70, 0x2D, 0x81, 0x1D,
+       0x02, 0x02, 0x06, 0x03, 0x25, 0x04, 0x01, 0x23, 0x81, 0x13, 0x00, 0x00,
+       0x81, 0x2E, 0x01, 0x10, 0x0F, 0x05, 0x02, 0x6B, 0x2A, 0x00, 0x00, 0x81,
+       0x14, 0x81, 0x2E, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x6B, 0x2A, 0x7D, 0x01,
+       0x0C, 0x08, 0x01, 0x0C, 0x81, 0x2A, 0x81, 0x13, 0x7D, 0x29, 0x01, 0x0C,
+       0x08, 0x01, 0x0C, 0x31, 0x05, 0x02, 0x5F, 0x2A, 0x00, 0x02, 0x03, 0x00,
+       0x03, 0x01, 0x02, 0x00, 0x81, 0x10, 0x02, 0x01, 0x02, 0x00, 0x3B, 0x29,
+       0x01, 0x00, 0x0F, 0x06, 0x02, 0x5D, 0x00, 0x81, 0x44, 0x04, 0x73, 0x00,
+       0x81, 0x34, 0x01, 0x01, 0x0E, 0x06, 0x02, 0x60, 0x2A, 0x81, 0x36, 0x29,
+       0x29, 0x58, 0x46, 0x01, 0x05, 0x11, 0x38, 0x06, 0x02, 0x60, 0x2A, 0x01,
+       0x08, 0x08, 0x29, 0x7C, 0x2F, 0x0B, 0x06, 0x0D, 0x29, 0x01, 0x01, 0x46,
+       0x0C, 0x3E, 0x29, 0x7C, 0x41, 0x7E, 0x41, 0x04, 0x01, 0x28, 0x00, 0x00,
+       0x81, 0x34, 0x81, 0x01, 0x2F, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x15, 0x28,
+       0x01, 0x01, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x81, 0x36, 0x06, 0x02, 0x63,
+       0x2A, 0x01, 0x02, 0x81, 0x01, 0x41, 0x04, 0x2B, 0x01, 0x02, 0x39, 0x0F,
+       0x06, 0x22, 0x28, 0x01, 0x0D, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x81, 0x36,
+       0x01, 0x0C, 0x0F, 0x05, 0x02, 0x63, 0x2A, 0x7D, 0x01, 0x0C, 0x81, 0x2A,
+       0x81, 0x02, 0x7D, 0x01, 0x0C, 0x31, 0x05, 0x02, 0x63, 0x2A, 0x04, 0x03,
+       0x63, 0x2A, 0x28, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x34, 0x81,
+       0x1C, 0x29, 0x06, 0x24, 0x81, 0x36, 0x06, 0x04, 0x81, 0x30, 0x04, 0x1A,
+       0x81, 0x34, 0x29, 0x01, 0x81, 0x7F, 0x0D, 0x06, 0x0F, 0x29, 0x81, 0x03,
+       0x08, 0x01, 0x00, 0x46, 0x41, 0x81, 0x03, 0x46, 0x81, 0x2A, 0x04, 0x02,
+       0x81, 0x3C, 0x04, 0x59, 0x81, 0x13, 0x81, 0x13, 0x00, 0x00, 0x81, 0x2F,
+       0x29, 0x58, 0x06, 0x07, 0x28, 0x06, 0x02, 0x61, 0x2A, 0x04, 0x73, 0x00,
+       0x00, 0x81, 0x37, 0x01, 0x03, 0x81, 0x35, 0x46, 0x28, 0x46, 0x00, 0x00,
+       0x81, 0x34, 0x81, 0x3C, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x81, 0x34,
+       0x81, 0x1C, 0x29, 0x06, 0x34, 0x81, 0x36, 0x03, 0x01, 0x81, 0x36, 0x03,
+       0x02, 0x02, 0x01, 0x01, 0x02, 0x11, 0x02, 0x01, 0x01, 0x06, 0x0D, 0x13,
+       0x02, 0x02, 0x01, 0x01, 0x0F, 0x02, 0x02, 0x01, 0x03, 0x0F, 0x38, 0x13,
+       0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x5B, 0x01, 0x02, 0x0C,
+       0x02, 0x01, 0x08, 0x0C, 0x38, 0x03, 0x00, 0x04, 0x49, 0x81, 0x13, 0x02,
+       0x00, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x31, 0x7A, 0x3F, 0x81,
+       0x13, 0x00, 0x00, 0x81, 0x34, 0x81, 0x1C, 0x81, 0x34, 0x81, 0x1C, 0x01,
+       0x00, 0x76, 0x40, 0x29, 0x06, 0x16, 0x81, 0x34, 0x29, 0x01, 0x20, 0x0B,
+       0x06, 0x0B, 0x01, 0x01, 0x46, 0x0C, 0x76, 0x2E, 0x38, 0x76, 0x40, 0x04,
+       0x01, 0x28, 0x04, 0x67, 0x81, 0x13, 0x81, 0x13, 0x00, 0x00, 0x01, 0x02,
+       0x81, 0x10, 0x81, 0x37, 0x01, 0x08, 0x0C, 0x81, 0x37, 0x08, 0x00, 0x00,
+       0x01, 0x03, 0x81, 0x10, 0x81, 0x37, 0x01, 0x08, 0x0C, 0x81, 0x37, 0x08,
+       0x01, 0x08, 0x0C, 0x81, 0x37, 0x08, 0x00, 0x00, 0x01, 0x01, 0x81, 0x10,
+       0x81, 0x37, 0x00, 0x00, 0x3C, 0x29, 0x56, 0x05, 0x01, 0x00, 0x28, 0x81,
+       0x44, 0x04, 0x75, 0x02, 0x03, 0x00, 0x81, 0x0A, 0x2F, 0x03, 0x01, 0x01,
+       0x00, 0x29, 0x02, 0x01, 0x0B, 0x06, 0x11, 0x29, 0x01, 0x01, 0x0C, 0x81,
+       0x09, 0x08, 0x2D, 0x02, 0x00, 0x0F, 0x06, 0x01, 0x00, 0x5A, 0x04, 0x69,
+       0x28, 0x01, 0x7F, 0x00, 0x00, 0x2B, 0x19, 0x37, 0x06, 0x05, 0x81, 0x42,
+       0x28, 0x04, 0x77, 0x01, 0x16, 0x81, 0x00, 0x41, 0x01, 0x00, 0x81, 0x55,
+       0x01, 0x00, 0x81, 0x54, 0x2B, 0x01, 0x17, 0x81, 0x00, 0x41, 0x00, 0x00,
+       0x01, 0x15, 0x81, 0x00, 0x41, 0x46, 0x50, 0x28, 0x50, 0x28, 0x2B, 0x00,
+       0x00, 0x01, 0x01, 0x46, 0x81, 0x3A, 0x00, 0x00, 0x46, 0x39, 0x81, 0x10,
+       0x46, 0x29, 0x06, 0x06, 0x81, 0x37, 0x28, 0x5B, 0x04, 0x77, 0x28, 0x00,
+       0x02, 0x03, 0x00, 0x70, 0x2D, 0x81, 0x12, 0x03, 0x01, 0x02, 0x01, 0x01,
+       0x0F, 0x13, 0x02, 0x01, 0x01, 0x04, 0x12, 0x01, 0x0F, 0x13, 0x02, 0x01,
+       0x01, 0x08, 0x12, 0x01, 0x0F, 0x13, 0x01, 0x00, 0x39, 0x0F, 0x06, 0x10,
+       0x28, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01,
+       0x4A, 0x04, 0x80, 0x56, 0x01, 0x01, 0x39, 0x0F, 0x06, 0x10, 0x28, 0x01,
+       0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04,
+       0x80, 0x40, 0x01, 0x02, 0x39, 0x0F, 0x06, 0x0F, 0x28, 0x01, 0x01, 0x01,
+       0x20, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x2B, 0x01,
+       0x03, 0x39, 0x0F, 0x06, 0x0E, 0x28, 0x28, 0x01, 0x10, 0x02, 0x00, 0x06,
+       0x03, 0x47, 0x04, 0x01, 0x48, 0x04, 0x17, 0x01, 0x04, 0x39, 0x0F, 0x06,
+       0x0E, 0x28, 0x28, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x47, 0x04, 0x01,
+       0x48, 0x04, 0x03, 0x62, 0x2A, 0x28, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C,
+       0x12, 0x01, 0x02, 0x10, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C, 0x12, 0x29,
+       0x59, 0x46, 0x01, 0x03, 0x0B, 0x13, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C,
+       0x12, 0x01, 0x01, 0x0F, 0x00, 0x00, 0x81, 0x12, 0x01, 0x0C, 0x12, 0x58,
+       0x00, 0x00, 0x1B, 0x01, 0x00, 0x6D, 0x2F, 0x29, 0x06, 0x20, 0x01, 0x01,
+       0x39, 0x0F, 0x06, 0x07, 0x28, 0x01, 0x00, 0x81, 0x16, 0x04, 0x11, 0x01,
+       0x02, 0x39, 0x0F, 0x06, 0x0A, 0x28, 0x6F, 0x2F, 0x06, 0x03, 0x01, 0x10,
+       0x38, 0x04, 0x01, 0x28, 0x04, 0x01, 0x28, 0x75, 0x2F, 0x05, 0x35, 0x30,
+       0x06, 0x32, 0x7F, 0x2F, 0x01, 0x14, 0x39, 0x0F, 0x06, 0x06, 0x28, 0x01,
+       0x02, 0x38, 0x04, 0x24, 0x01, 0x15, 0x39, 0x0F, 0x06, 0x0B, 0x28, 0x81,
+       0x1F, 0x06, 0x04, 0x01, 0x7F, 0x81, 0x16, 0x04, 0x13, 0x01, 0x16, 0x39,
+       0x0F, 0x06, 0x06, 0x28, 0x01, 0x01, 0x38, 0x04, 0x07, 0x28, 0x01, 0x04,
+       0x38, 0x01, 0x00, 0x28, 0x19, 0x06, 0x03, 0x01, 0x08, 0x38, 0x00, 0x00,
+       0x1B, 0x29, 0x05, 0x10, 0x30, 0x06, 0x0D, 0x7F, 0x2F, 0x01, 0x15, 0x0F,
+       0x06, 0x05, 0x28, 0x81, 0x1F, 0x04, 0x01, 0x22, 0x00, 0x00, 0x81, 0x42,
+       0x01, 0x07, 0x13, 0x01, 0x01, 0x10, 0x06, 0x02, 0x6B, 0x2A, 0x00, 0x01,
+       0x03, 0x00, 0x2B, 0x19, 0x06, 0x06, 0x02, 0x00, 0x81, 0x00, 0x41, 0x00,
+       0x81, 0x42, 0x28, 0x04, 0x72, 0x00, 0x01, 0x14, 0x81, 0x45, 0x01, 0x01,
+       0x81, 0x55, 0x2B, 0x29, 0x01, 0x00, 0x81, 0x3D, 0x01, 0x16, 0x81, 0x45,
+       0x81, 0x49, 0x2B, 0x00, 0x00, 0x01, 0x0B, 0x81, 0x55, 0x4C, 0x29, 0x29,
+       0x01, 0x03, 0x08, 0x81, 0x54, 0x81, 0x54, 0x14, 0x29, 0x56, 0x06, 0x02,
+       0x28, 0x00, 0x81, 0x54, 0x1E, 0x29, 0x06, 0x06, 0x7D, 0x46, 0x81, 0x4D,
+       0x04, 0x76, 0x28, 0x04, 0x6A, 0x00, 0x01, 0x00, 0x81, 0x4F, 0x81, 0x0B,
+       0x2D, 0x01, 0x86, 0x03, 0x11, 0x06, 0x06, 0x5C, 0x01, 0x00, 0x81, 0x50,
+       0x08, 0x4B, 0x08, 0x01, 0x03, 0x08, 0x01, 0x0D, 0x81, 0x55, 0x81, 0x54,
+       0x01, 0x00, 0x81, 0x4F, 0x81, 0x55, 0x01, 0x01, 0x81, 0x4F, 0x28, 0x81,
+       0x0B, 0x2D, 0x01, 0x86, 0x03, 0x11, 0x06, 0x0B, 0x01, 0x00, 0x81, 0x50,
+       0x81, 0x53, 0x01, 0x01, 0x81, 0x50, 0x28, 0x4B, 0x81, 0x53, 0x16, 0x15,
+       0x29, 0x56, 0x06, 0x02, 0x28, 0x00, 0x81, 0x53, 0x1F, 0x29, 0x06, 0x06,
+       0x7D, 0x46, 0x81, 0x4D, 0x04, 0x76, 0x28, 0x04, 0x6A, 0x00, 0x81, 0x14,
+       0x01, 0x14, 0x81, 0x55, 0x01, 0x0C, 0x81, 0x54, 0x7D, 0x01, 0x0C, 0x81,
+       0x4D, 0x00, 0x03, 0x03, 0x00, 0x01, 0x02, 0x81, 0x55, 0x01, 0x80, 0x46,
+       0x81, 0x01, 0x2F, 0x01, 0x02, 0x0F, 0x06, 0x0C, 0x02, 0x00, 0x06, 0x04,
+       0x01, 0x05, 0x04, 0x02, 0x01, 0x1D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x01,
+       0x7E, 0x2F, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02, 0x01, 0x00, 0x03, 0x02,
+       0x02, 0x01, 0x02, 0x02, 0x08, 0x29, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08,
+       0x81, 0x54, 0x81, 0x0B, 0x2D, 0x81, 0x53, 0x81, 0x04, 0x01, 0x04, 0x17,
+       0x81, 0x04, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x33, 0x81, 0x04, 0x01, 0x20,
+       0x81, 0x4D, 0x01, 0x20, 0x81, 0x55, 0x81, 0x05, 0x01, 0x20, 0x81, 0x4D,
+       0x70, 0x2D, 0x81, 0x53, 0x01, 0x00, 0x81, 0x55, 0x02, 0x01, 0x02, 0x02,
+       0x08, 0x29, 0x06, 0x31, 0x81, 0x53, 0x02, 0x01, 0x29, 0x06, 0x14, 0x01,
+       0x83, 0xFE, 0x01, 0x81, 0x53, 0x01, 0x04, 0x09, 0x29, 0x81, 0x53, 0x5B,
+       0x81, 0x02, 0x46, 0x81, 0x4E, 0x04, 0x01, 0x28, 0x02, 0x02, 0x06, 0x0F,
+       0x01, 0x01, 0x81, 0x53, 0x01, 0x01, 0x81, 0x53, 0x7E, 0x2F, 0x01, 0x08,
+       0x09, 0x81, 0x55, 0x04, 0x01, 0x28, 0x00, 0x00, 0x01, 0x0E, 0x81, 0x55,
+       0x01, 0x00, 0x81, 0x54, 0x00, 0x03, 0x70, 0x2D, 0x81, 0x3F, 0x05, 0x01,
+       0x00, 0x76, 0x2E, 0x01, 0x00, 0x81, 0x18, 0x12, 0x01, 0x01, 0x13, 0x58,
+       0x06, 0x03, 0x5A, 0x04, 0x74, 0x03, 0x00, 0x28, 0x02, 0x00, 0x24, 0x29,
+       0x56, 0x06, 0x02, 0x36, 0x2A, 0x03, 0x01, 0x81, 0x0B, 0x2D, 0x01, 0x86,
+       0x03, 0x11, 0x03, 0x02, 0x01, 0x0C, 0x81, 0x55, 0x02, 0x01, 0x78, 0x2F,
+       0x08, 0x02, 0x02, 0x01, 0x02, 0x13, 0x08, 0x01, 0x06, 0x08, 0x81, 0x54,
+       0x01, 0x03, 0x81, 0x55, 0x02, 0x00, 0x81, 0x53, 0x77, 0x78, 0x2F, 0x81,
+       0x4E, 0x02, 0x02, 0x06, 0x11, 0x81, 0x08, 0x2F, 0x81, 0x55, 0x70, 0x2D,
+       0x81, 0x40, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x08, 0x81, 0x55, 0x02, 0x01,
+       0x81, 0x53, 0x7D, 0x02, 0x01, 0x81, 0x4D, 0x00, 0x00, 0x4F, 0x29, 0x01,
+       0x00, 0x0F, 0x06, 0x02, 0x5D, 0x00, 0x81, 0x42, 0x28, 0x04, 0x72, 0x00,
+       0x29, 0x81, 0x55, 0x81, 0x4D, 0x00, 0x00, 0x01, 0x00, 0x70, 0x2D, 0x81,
+       0x3E, 0x06, 0x0E, 0x5C, 0x39, 0x06, 0x0A, 0x01, 0x80, 0x41, 0x81, 0x55,
+       0x01, 0x80, 0x42, 0x81, 0x55, 0x45, 0x06, 0x08, 0x5A, 0x39, 0x06, 0x04,
+       0x01, 0x01, 0x81, 0x55, 0x44, 0x06, 0x09, 0x5A, 0x39, 0x06, 0x05, 0x01,
+       0x80, 0x40, 0x81, 0x55, 0x46, 0x28, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00,
+       0x45, 0x44, 0x38, 0x05, 0x16, 0x01, 0x01, 0x01, 0x80, 0x7C, 0x81, 0x51,
+       0x03, 0x00, 0x01, 0x03, 0x01, 0x80, 0x7C, 0x81, 0x51, 0x02, 0x00, 0x08,
+       0x46, 0x28, 0x00, 0x45, 0x06, 0x08, 0x01, 0x01, 0x43, 0x28, 0x81, 0x51,
+       0x03, 0x00, 0x44, 0x06, 0x0B, 0x01, 0x03, 0x43, 0x28, 0x81, 0x51, 0x02,
+       0x00, 0x08, 0x03, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+       0x04, 0x81, 0x52, 0x01, 0x05, 0x81, 0x52, 0x01, 0x06, 0x81, 0x52, 0x01,
+       0x03, 0x81, 0x52, 0x01, 0x02, 0x81, 0x52, 0x0A, 0x5D, 0x00, 0x01, 0x03,
+       0x00, 0x39, 0x01, 0x01, 0x02, 0x00, 0x0C, 0x13, 0x05, 0x01, 0x00, 0x5C,
+       0x01, 0x03, 0x3A, 0x06, 0x09, 0x02, 0x00, 0x81, 0x55, 0x01, 0x02, 0x3A,
+       0x81, 0x55, 0x00, 0x00, 0x29, 0x01, 0x08, 0x4D, 0x81, 0x55, 0x81, 0x55,
+       0x00, 0x00, 0x29, 0x01, 0x10, 0x4D, 0x81, 0x55, 0x81, 0x53, 0x00, 0x00,
+       0x29, 0x50, 0x06, 0x02, 0x28, 0x00, 0x81, 0x42, 0x28, 0x04, 0x75
 };
 
 static const uint16_t t0_caddr[] = {
 };
 
 static const uint16_t t0_caddr[] = {
@@ -613,101 +788,117 @@ static const uint16_t t0_caddr[] = {
        75,
        79,
        83,
        75,
        79,
        83,
-       88,
-       93,
-       98,
-       103,
-       108,
-       113,
-       118,
-       123,
-       128,
-       133,
-       138,
-       143,
-       148,
-       153,
+       87,
+       91,
+       95,
+       99,
+       104,
+       109,
+       114,
+       119,
+       124,
+       129,
+       134,
+       139,
+       144,
+       149,
+       154,
        159,
        164,
        169,
        159,
        164,
        169,
-       174,
-       179,
-       184,
-       189,
-       194,
-       199,
-       204,
-       209,
-       214,
-       219,
-       224,
-       229,
-       234,
-       239,
-       244,
-       249,
-       254,
-       259,
-       268,
-       272,
-       297,
-       303,
-       323,
-       334,
-       371,
-       431,
-       435,
-       471,
-       481,
-       557,
-       571,
-       577,
-       637,
-       657,
-       710,
-       1267,
-       1352,
-       1385,
-       1410,
-       1458,
-       1532,
-       1581,
-       1596,
-       1607,
-       1613,
-       1684,
-       1725,
-       1738,
-       1757,
-       1764,
-       1776,
-       1811,
-       1840,
-       1852,
-       1859,
-       1875,
-       2013,
-       2022,
-       2035,
-       2044,
-       2051,
-       2157,
-       2179,
-       2193,
+       175,
+       180,
+       185,
+       190,
+       195,
+       200,
+       205,
+       210,
+       215,
+       220,
+       225,
+       230,
+       235,
+       240,
+       245,
+       250,
+       255,
+       260,
+       265,
+       270,
+       275,
+       284,
+       288,
+       316,
+       322,
+       343,
+       354,
+       391,
+       523,
+       527,
+       563,
+       573,
+       650,
+       664,
+       671,
+       731,
+       752,
+       776,
+       829,
+       915,
+       1023,
+       1035,
+       1630,
+       1636,
+       1713,
+       1724,
+       1759,
+       1785,
+       1833,
+       1910,
+       1963,
+       1978,
+       1989,
+       1995,
+       2064,
+       2076,
+       2119,
+       2133,
+       2153,
+       2161,
+       2173,
        2210,
        2210,
-       2233,
-       2269,
-       2285,
-       2439,
-       2449,
-       2558,
-       2573,
-       2580,
-       2590,
-       2600
+       2241,
+       2254,
+       2261,
+       2278,
+       2417,
+       2427,
+       2441,
+       2451,
+       2459,
+       2565,
+       2587,
+       2601,
+       2619,
+       2642,
+       2679,
+       2767,
+       2784,
+       2945,
+       2955,
+       3066,
+       3081,
+       3088,
+       3137,
+       3198,
+       3224,
+       3253,
+       3263,
+       3273
 };
 
 };
 
-#define T0_INTERPRETED   68
+#define T0_INTERPRETED   86
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
@@ -728,7 +919,7 @@ name(void *ctx) \
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
-T0_DEFENTRY(br_ssl_hs_server_init_main, 133)
+T0_DEFENTRY(br_ssl_hs_server_init_main, 155)
 
 void
 br_ssl_hs_server_run(void *t0ctx)
 
 void
 br_ssl_hs_server_run(void *t0ctx)
@@ -853,6 +1044,11 @@ br_ssl_hs_server_run(void *t0ctx)
                                }
                                break;
                        case 10: {
                                }
                                break;
                        case 10: {
+                               /* -rot */
+ T0_NROT(); 
+                               }
+                               break;
+                       case 11: {
                                /* < */
 
        int32_t b = T0_POPi();
                                /* < */
 
        int32_t b = T0_POPi();
@@ -861,7 +1057,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 11: {
+                       case 12: {
                                /* << */
 
        int c = (int)T0_POPi();
                                /* << */
 
        int c = (int)T0_POPi();
@@ -870,7 +1066,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 12: {
+                       case 13: {
                                /* <= */
 
        int32_t b = T0_POPi();
                                /* <= */
 
        int32_t b = T0_POPi();
@@ -879,7 +1075,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 13: {
+                       case 14: {
                                /* <> */
 
        uint32_t b = T0_POP();
                                /* <> */
 
        uint32_t b = T0_POP();
@@ -888,7 +1084,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 14: {
+                       case 15: {
                                /* = */
 
        uint32_t b = T0_POP();
                                /* = */
 
        uint32_t b = T0_POP();
@@ -897,7 +1093,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 15: {
+                       case 16: {
                                /* > */
 
        int32_t b = T0_POPi();
                                /* > */
 
        int32_t b = T0_POPi();
@@ -906,7 +1102,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 16: {
+                       case 17: {
                                /* >= */
 
        int32_t b = T0_POPi();
                                /* >= */
 
        int32_t b = T0_POPi();
@@ -915,7 +1111,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 17: {
+                       case 18: {
                                /* >> */
 
        int c = (int)T0_POPi();
                                /* >> */
 
        int c = (int)T0_POPi();
@@ -924,7 +1120,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 18: {
+                       case 19: {
                                /* and */
 
        uint32_t b = T0_POP();
                                /* and */
 
        uint32_t b = T0_POP();
@@ -933,22 +1129,49 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 19: {
+                       case 20: {
                                /* begin-cert */
 
                                /* begin-cert */
 
-       if (CTX->chain_len == 0) {
+       if (ENG->chain_len == 0) {
                T0_PUSHi(-1);
        } else {
                T0_PUSHi(-1);
        } else {
-               CTX->cert_cur = CTX->chain->data;
-               CTX->cert_len = CTX->chain->data_len;
-               CTX->chain ++;
-               CTX->chain_len --;
-               T0_PUSH(CTX->cert_len);
+               ENG->cert_cur = ENG->chain->data;
+               ENG->cert_len = ENG->chain->data_len;
+               ENG->chain ++;
+               ENG->chain_len --;
+               T0_PUSH(ENG->cert_len);
        }
 
                                }
                                break;
        }
 
                                }
                                break;
-                       case 20: {
+                       case 21: {
+                               /* begin-ta-name */
+
+       const br_x500_name *dn;
+       if (CTX->cur_dn_index >= CTX->num_tas) {
+               T0_PUSHi(-1);
+       } else {
+               if (CTX->ta_names == NULL) {
+                       dn = &CTX->tas[CTX->cur_dn_index].dn;
+               } else {
+                       dn = &CTX->ta_names[CTX->cur_dn_index];
+               }
+               CTX->cur_dn_index ++;
+               CTX->cur_dn = dn->data;
+               CTX->cur_dn_len = dn->len;
+               T0_PUSH(CTX->cur_dn_len);
+       }
+
+                               }
+                               break;
+                       case 22: {
+                               /* begin-ta-name-list */
+
+       CTX->cur_dn_index = 0;
+
+                               }
+                               break;
+                       case 23: {
                                /* bzero */
 
        size_t len = (size_t)T0_POP();
                                /* bzero */
 
        size_t len = (size_t)T0_POP();
@@ -957,7 +1180,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 21: {
+                       case 24: {
                                /* call-policy-handler */
 
        int x;
                                /* call-policy-handler */
 
        int x;
@@ -967,20 +1190,20 @@ br_ssl_hs_server_run(void *t0ctx)
                CTX->policy_vtable, CTX, &choices);
        ENG->session.cipher_suite = choices.cipher_suite;
        CTX->sign_hash_id = choices.hash_id;
                CTX->policy_vtable, CTX, &choices);
        ENG->session.cipher_suite = choices.cipher_suite;
        CTX->sign_hash_id = choices.hash_id;
-       CTX->chain = choices.chain;
-       CTX->chain_len = choices.chain_len;
+       ENG->chain = choices.chain;
+       ENG->chain_len = choices.chain_len;
        T0_PUSHi(-(x != 0));
 
                                }
                                break;
        T0_PUSHi(-(x != 0));
 
                                }
                                break;
-                       case 22: {
+                       case 25: {
                                /* can-output? */
 
        T0_PUSHi(-(ENG->hlen_out > 0));
 
                                }
                                break;
                                /* can-output? */
 
        T0_PUSHi(-(ENG->hlen_out > 0));
 
                                }
                                break;
-                       case 23: {
+                       case 26: {
                                /* check-resume */
 
        if (ENG->session.session_id_len == 32
                                /* check-resume */
 
        if (ENG->session.session_id_len == 32
@@ -994,12 +1217,12 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 24: {
+                       case 27: {
                                /* co */
  T0_CO(); 
                                }
                                break;
                                /* co */
  T0_CO(); 
                                }
                                break;
-                       case 25: {
+                       case 28: {
                                /* compute-Finished-inner */
 
        int prf_id = T0_POP();
                                /* compute-Finished-inner */
 
        int prf_id = T0_POP();
@@ -1022,23 +1245,75 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 26: {
+                       case 29: {
+                               /* compute-hash-CV */
+
+       int i;
+
+       for (i = 1; i <= 6; i ++) {
+               br_multihash_out(&ENG->mhash, i,
+                       ENG->pad + HASH_PAD_OFF[i - 1]);
+       }
+
+                               }
+                               break;
+                       case 30: {
                                /* copy-cert-chunk */
 
        size_t clen;
 
                                /* copy-cert-chunk */
 
        size_t clen;
 
-       clen = CTX->cert_len;
+       clen = ENG->cert_len;
        if (clen > sizeof ENG->pad) {
                clen = sizeof ENG->pad;
        }
        if (clen > sizeof ENG->pad) {
                clen = sizeof ENG->pad;
        }
-       memcpy(ENG->pad, CTX->cert_cur, clen);
-       CTX->cert_cur += clen;
-       CTX->cert_len -= clen;
+       memcpy(ENG->pad, ENG->cert_cur, clen);
+       ENG->cert_cur += clen;
+       ENG->cert_len -= clen;
        T0_PUSH(clen);
 
                                }
                                break;
        T0_PUSH(clen);
 
                                }
                                break;
-                       case 27: {
+                       case 31: {
+                               /* copy-dn-chunk */
+
+       size_t clen;
+
+       clen = CTX->cur_dn_len;
+       if (clen > sizeof ENG->pad) {
+               clen = sizeof ENG->pad;
+       }
+       memcpy(ENG->pad, CTX->cur_dn, clen);
+       CTX->cur_dn += clen;
+       CTX->cur_dn_len -= clen;
+       T0_PUSH(clen);
+
+                               }
+                               break;
+                       case 32: {
+                               /* copy-hash-CV */
+
+       int id = T0_POP();
+       size_t off, len;
+
+       if (id == 0) {
+               off = 0;
+               len = 36;
+       } else {
+               if (br_multihash_getimpl(&ENG->mhash, id) == 0) {
+                       T0_PUSH(0);
+                       T0_RET();
+               }
+               off = HASH_PAD_OFF[id - 1];
+               len = HASH_PAD_OFF[id] - off;
+       }
+       memcpy(CTX->hash_CV, ENG->pad + off, len);
+       CTX->hash_CV_len = len;
+       CTX->hash_CV_id = id;
+       T0_PUSHi(-1);
+
+                               }
+                               break;
+                       case 33: {
                                /* data-get8 */
 
        size_t addr = T0_POP();
                                /* data-get8 */
 
        size_t addr = T0_POP();
@@ -1046,14 +1321,14 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 28: {
+                       case 34: {
                                /* discard-input */
 
        ENG->hlen_in = 0;
 
                                }
                                break;
                                /* discard-input */
 
        ENG->hlen_in = 0;
 
                                }
                                break;
-                       case 29: {
+                       case 35: {
                                /* do-ecdh */
 
        int prf_id = T0_POPi();
                                /* do-ecdh */
 
        int prf_id = T0_POPi();
@@ -1062,7 +1337,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 30: {
+                       case 36: {
                                /* do-ecdhe-part1 */
 
        int curve = T0_POPi();
                                /* do-ecdhe-part1 */
 
        int curve = T0_POPi();
@@ -1070,7 +1345,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 31: {
+                       case 37: {
                                /* do-ecdhe-part2 */
 
        int prf_id = T0_POPi();
                                /* do-ecdhe-part2 */
 
        int prf_id = T0_POPi();
@@ -1079,7 +1354,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 32: {
+                       case 38: {
                                /* do-rsa-decrypt */
 
        int prf_id = T0_POPi();
                                /* do-rsa-decrypt */
 
        int prf_id = T0_POPi();
@@ -1088,17 +1363,24 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 33: {
+                       case 39: {
+                               /* do-static-ecdh */
+
+       do_static_ecdh(CTX, T0_POP());
+
+                               }
+                               break;
+                       case 40: {
                                /* drop */
  (void)T0_POP(); 
                                }
                                break;
                                /* drop */
  (void)T0_POP(); 
                                }
                                break;
-                       case 34: {
+                       case 41: {
                                /* dup */
  T0_PUSH(T0_PEEK(0)); 
                                }
                                break;
                                /* dup */
  T0_PUSH(T0_PEEK(0)); 
                                }
                                break;
-                       case 35: {
+                       case 42: {
                                /* fail */
 
        br_ssl_engine_fail(ENG, (int)T0_POPi());
                                /* fail */
 
        br_ssl_engine_fail(ENG, (int)T0_POPi());
@@ -1106,14 +1388,31 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 36: {
+                       case 43: {
                                /* flush-record */
 
        br_ssl_engine_flush_record(ENG);
 
                                }
                                break;
                                /* flush-record */
 
        br_ssl_engine_flush_record(ENG);
 
                                }
                                break;
-                       case 37: {
+                       case 44: {
+                               /* get-key-type-usages */
+
+       const br_x509_class *xc;
+       const br_x509_pkey *pk;
+       unsigned usages;
+
+       xc = *(ENG->x509ctx);
+       pk = xc->get_pkey(ENG->x509ctx, &usages);
+       if (pk == NULL) {
+               T0_PUSH(0);
+       } else {
+               T0_PUSH(pk->key_type | usages);
+       }
+
+                               }
+                               break;
+                       case 45: {
                                /* get16 */
 
        size_t addr = (size_t)T0_POP();
                                /* get16 */
 
        size_t addr = (size_t)T0_POP();
@@ -1121,7 +1420,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 38: {
+                       case 46: {
                                /* get32 */
 
        size_t addr = (size_t)T0_POP();
                                /* get32 */
 
        size_t addr = (size_t)T0_POP();
@@ -1129,7 +1428,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 39: {
+                       case 47: {
                                /* get8 */
 
        size_t addr = (size_t)T0_POP();
                                /* get8 */
 
        size_t addr = (size_t)T0_POP();
@@ -1137,14 +1436,14 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 40: {
+                       case 48: {
                                /* has-input? */
 
        T0_PUSHi(-(ENG->hlen_in != 0));
 
                                }
                                break;
                                /* has-input? */
 
        T0_PUSHi(-(ENG->hlen_in != 0));
 
                                }
                                break;
-                       case 41: {
+                       case 49: {
                                /* memcmp */
 
        size_t len = (size_t)T0_POP();
                                /* memcmp */
 
        size_t len = (size_t)T0_POP();
@@ -1155,7 +1454,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 42: {
+                       case 50: {
                                /* memcpy */
 
        size_t len = (size_t)T0_POP();
                                /* memcpy */
 
        size_t len = (size_t)T0_POP();
@@ -1165,7 +1464,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 43: {
+                       case 51: {
                                /* mkrand */
 
        size_t len = (size_t)T0_POP();
                                /* mkrand */
 
        size_t len = (size_t)T0_POP();
@@ -1174,21 +1473,21 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 44: {
+                       case 52: {
                                /* more-incoming-bytes? */
 
        T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
 
                                }
                                break;
                                /* more-incoming-bytes? */
 
        T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
 
                                }
                                break;
-                       case 45: {
+                       case 53: {
                                /* multihash-init */
 
        br_multihash_init(&ENG->mhash);
 
                                }
                                break;
                                /* multihash-init */
 
        br_multihash_init(&ENG->mhash);
 
                                }
                                break;
-                       case 46: {
+                       case 54: {
                                /* neg */
 
        uint32_t a = T0_POP();
                                /* neg */
 
        uint32_t a = T0_POP();
@@ -1196,7 +1495,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 47: {
+                       case 55: {
                                /* not */
 
        uint32_t a = T0_POP();
                                /* not */
 
        uint32_t a = T0_POP();
@@ -1204,7 +1503,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 48: {
+                       case 56: {
                                /* or */
 
        uint32_t b = T0_POP();
                                /* or */
 
        uint32_t b = T0_POP();
@@ -1213,12 +1512,17 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 49: {
+                       case 57: {
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
-                       case 50: {
+                       case 58: {
+                               /* pick */
+ T0_PICK(T0_POP()); 
+                               }
+                               break;
+                       case 59: {
                                /* read-chunk-native */
 
        size_t clen = ENG->hlen_in;
                                /* read-chunk-native */
 
        size_t clen = ENG->hlen_in;
@@ -1242,7 +1546,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 51: {
+                       case 60: {
                                /* read8-native */
 
        if (ENG->hlen_in > 0) {
                                /* read8-native */
 
        if (ENG->hlen_in > 0) {
@@ -1260,7 +1564,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 52: {
+                       case 61: {
                                /* save-session */
 
        if (CTX->cache_vtable != NULL) {
                                /* save-session */
 
        if (CTX->cache_vtable != NULL) {
@@ -1270,7 +1574,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 53: {
+                       case 62: {
                                /* set-max-frag-len */
 
        size_t max_frag_len = T0_POP();
                                /* set-max-frag-len */
 
        size_t max_frag_len = T0_POP();
@@ -1289,7 +1593,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 54: {
+                       case 63: {
                                /* set16 */
 
        size_t addr = (size_t)T0_POP();
                                /* set16 */
 
        size_t addr = (size_t)T0_POP();
@@ -1297,7 +1601,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 55: {
+                       case 64: {
                                /* set32 */
 
        size_t addr = (size_t)T0_POP();
                                /* set32 */
 
        size_t addr = (size_t)T0_POP();
@@ -1305,7 +1609,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 56: {
+                       case 65: {
                                /* set8 */
 
        size_t addr = (size_t)T0_POP();
                                /* set8 */
 
        size_t addr = (size_t)T0_POP();
@@ -1313,7 +1617,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 57: {
+                       case 66: {
                                /* supported-curves */
 
        uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
                                /* supported-curves */
 
        uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
@@ -1321,7 +1625,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 58: {
+                       case 67: {
                                /* supported-hash-functions */
 
        int i;
                                /* supported-hash-functions */
 
        int i;
@@ -1340,12 +1644,26 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 59: {
+                       case 68: {
+                               /* supports-ecdsa? */
+
+       T0_PUSHi(-(ENG->iecdsa != 0));
+
+                               }
+                               break;
+                       case 69: {
+                               /* supports-rsa-sign? */
+
+       T0_PUSHi(-(ENG->irsavrfy != 0));
+
+                               }
+                               break;
+                       case 70: {
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
-                       case 60: {
+                       case 71: {
                                /* switch-aesgcm-in */
 
        int is_client, prf_id;
                                /* switch-aesgcm-in */
 
        int is_client, prf_id;
@@ -1359,7 +1677,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 61: {
+                       case 72: {
                                /* switch-aesgcm-out */
 
        int is_client, prf_id;
                                /* switch-aesgcm-out */
 
        int is_client, prf_id;
@@ -1373,7 +1691,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 62: {
+                       case 73: {
                                /* switch-cbc-in */
 
        int is_client, prf_id, mac_id, aes;
                                /* switch-cbc-in */
 
        int is_client, prf_id, mac_id, aes;
@@ -1389,7 +1707,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 63: {
+                       case 74: {
                                /* switch-cbc-out */
 
        int is_client, prf_id, mac_id, aes;
                                /* switch-cbc-out */
 
        int is_client, prf_id, mac_id, aes;
@@ -1405,21 +1723,40 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 64: {
+                       case 75: {
+                               /* ta-names-total-length */
+
+       size_t u, len;
+
+       len = 0;
+       if (CTX->ta_names != NULL) {
+               for (u = 0; u < CTX->num_tas; u ++) {
+                       len += CTX->ta_names[u].len + 2;
+               }
+       } else if (CTX->tas != NULL) {
+               for (u = 0; u < CTX->num_tas; u ++) {
+                       len += CTX->tas[u].dn.len + 2;
+               }
+       }
+       T0_PUSH(len);
+
+                               }
+                               break;
+                       case 76: {
                                /* total-chain-length */
 
        size_t u;
        uint32_t total;
 
        total = 0;
                                /* total-chain-length */
 
        size_t u;
        uint32_t total;
 
        total = 0;
-       for (u = 0; u < CTX->chain_len; u ++) {
-               total += 3 + (uint32_t)CTX->chain[u].data_len;
+       for (u = 0; u < ENG->chain_len; u ++) {
+               total += 3 + (uint32_t)ENG->chain[u].data_len;
        }
        T0_PUSH(total);
 
                                }
                                break;
        }
        T0_PUSH(total);
 
                                }
                                break;
-                       case 65: {
+                       case 77: {
                                /* u>> */
 
        int c = (int)T0_POPi();
                                /* u>> */
 
        int c = (int)T0_POPi();
@@ -1428,7 +1765,17 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 66: {
+                       case 78: {
+                               /* verify-CV-sig */
+
+       int err;
+
+       err = verify_CV_sig(CTX, T0_POP());
+       T0_PUSHi(err);
+
+                               }
+                               break;
+                       case 79: {
                                /* write-blob-chunk */
 
        size_t clen = ENG->hlen_out;
                                /* write-blob-chunk */
 
        size_t clen = ENG->hlen_out;
@@ -1452,7 +1799,7 @@ br_ssl_hs_server_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 67: {
+                       case 80: {
                                /* write8-native */
 
        unsigned char x;
                                /* write8-native */
 
        unsigned char x;
@@ -1469,6 +1816,60 @@ br_ssl_hs_server_run(void *t0ctx)
                T0_PUSHi(0);
        }
 
                T0_PUSHi(0);
        }
 
+                               }
+                               break;
+                       case 81: {
+                               /* x509-append */
+
+       const br_x509_class *xc;
+       size_t len;
+
+       xc = *(ENG->x509ctx);
+       len = T0_POP();
+       xc->append(ENG->x509ctx, ENG->pad, len);
+
+                               }
+                               break;
+                       case 82: {
+                               /* x509-end-cert */
+
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       xc->end_cert(ENG->x509ctx);
+
+                               }
+                               break;
+                       case 83: {
+                               /* x509-end-chain */
+
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       T0_PUSH(xc->end_chain(ENG->x509ctx));
+
+                               }
+                               break;
+                       case 84: {
+                               /* x509-start-cert */
+
+       const br_x509_class *xc;
+
+       xc = *(ENG->x509ctx);
+       xc->start_cert(ENG->x509ctx, T0_POP());
+
+                               }
+                               break;
+                       case 85: {
+                               /* x509-start-chain */
+
+       const br_x509_class *xc;
+       uint32_t bc;
+
+       bc = T0_POP();
+       xc = *(ENG->x509ctx);
+       xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
+
                                }
                                break;
                        }
                                }
                                break;
                        }
index 8176429..862e0fb 100644 (file)
@@ -140,6 +140,35 @@ do_ecdh(br_ssl_server_context *ctx, int prf_id,
        ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
 }
 
        ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
 }
 
+/*
+ * Do the full static ECDH key exchange. When this function is called,
+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),
+ * and the client's public key (from its certificate) has type EC and is
+ * apt for key exchange.
+ */
+static void
+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)
+{
+       unsigned char cpoint[133];
+       size_t cpoint_len;
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       cpoint_len = pk->key.ec.qlen;
+       if (cpoint_len > sizeof cpoint) {
+               /*
+                * If the point is larger than our buffer then we need to
+                * restrict it. Length 2 is not a valid point length, so
+                * the ECDH will fail.
+                */
+               cpoint_len = 2;
+       }
+       memcpy(cpoint, pk->key.ec.q, cpoint_len);
+       do_ecdh(ctx, prf_id, cpoint, cpoint_len);
+}
+
 /*
  * Do the ECDHE key exchange (part 1: generation of transient key, and
  * computing of the point to send to the client). Returned value is the
 /*
  * Do the ECDHE key exchange (part 1: generation of transient key, and
  * computing of the point to send to the client). Returned value is the
@@ -258,6 +287,94 @@ do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
        memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
 }
 
        memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
 }
 
+/*
+ * Offset for hash value within the pad (when obtaining all hash values,
+ * in preparation for verification of the CertificateVerify message).
+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value
+ * is used to get the total length.
+ */
+static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 };
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+       HASH_OID_SHA1,
+       HASH_OID_SHA224,
+       HASH_OID_SHA256,
+       HASH_OID_SHA384,
+       HASH_OID_SHA512
+};
+
+/*
+ * Verify the signature in CertificateVerify. Returned value is 0 on
+ * success, or a non-zero error code. Lack of implementation of the
+ * designated signature algorithm is reported as a "bad signature"
+ * error (because it means that the peer did not honour our advertised
+ * set of supported signature algorithms).
+ */
+static int
+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)
+{
+       const br_x509_class **xc;
+       const br_x509_pkey *pk;
+       int id;
+
+       id = ctx->hash_CV_id;
+       xc = ctx->eng.x509ctx;
+       pk = (*xc)->get_pkey(xc, NULL);
+       if (pk->key_type == BR_KEYTYPE_RSA) {
+               unsigned char tmp[64];
+               const unsigned char *hash_oid;
+
+               if (id == 0) {
+                       hash_oid = NULL;
+               } else {
+                       hash_oid = HASH_OID[id - 2];
+               }
+               if (ctx->eng.irsavrfy == 0) {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+               if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+                       hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp)
+                       || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0)
+               {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+       } else {
+               if (ctx->eng.iecdsa == 0) {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+               if (!ctx->eng.iecdsa(ctx->eng.iec,
+                       ctx->hash_CV, ctx->hash_CV_len,
+                       &pk->key.ec, ctx->eng.pad, sig_len))
+               {
+                       return BR_ERR_BAD_SIGNATURE;
+               }
+       }
+       return 0;
+}
+
 }
 
 \ =======================================================================
 }
 
 \ =======================================================================
@@ -386,26 +503,7 @@ cc: set-max-frag-len ( len -- ) {
        \ Open extension value.
        read16 open-elt
 
        \ Open extension value.
        read16 open-elt
 
-       \ Clear list of supported signature algorithms.
-       0 addr-hashes set16
-
-       \ Get list of algorithms length.
-       read16 open-elt
-       begin dup while
-               read8 { hash } read8 { sign }
-               \ We keep the value if the signature is either 1 (RSA) or
-               \ 3 (ECDSA), and the hash is one of the SHA-* functions
-               \ (2 to 6, from SHA-1 to SHA-512). Note that we reject
-               \ any use of MD5. Also, we do not keep track of the client
-               \ preferences.
-               hash 2 >= hash 6 <= and
-               sign 1 = sign 3 = or
-               and if
-                       addr-hashes get16
-                       1 sign 1- 2 << hash + << or addr-hashes set16
-               then
-       repeat
-       close-elt
+       read-list-sign-algos addr-hashes set16
 
        \ Close extension value.
        close-elt ;
 
        \ Close extension value.
        close-elt ;
@@ -440,8 +538,8 @@ cc: call-policy-handler ( -- bool ) {
                CTX->policy_vtable, CTX, &choices);
        ENG->session.cipher_suite = choices.cipher_suite;
        CTX->sign_hash_id = choices.hash_id;
                CTX->policy_vtable, CTX, &choices);
        ENG->session.cipher_suite = choices.cipher_suite;
        CTX->sign_hash_id = choices.hash_id;
-       CTX->chain = choices.chain;
-       CTX->chain_len = choices.chain_len;
+       ENG->chain = choices.chain;
+       ENG->chain_len = choices.chain_len;
        T0_PUSHi(-(x != 0));
 }
 
        T0_PUSHi(-(x != 0));
 }
 
@@ -667,11 +765,14 @@ cc: save-session ( -- ) {
        ok-compression ifnot 40 fail-alert then
 
        \ Filter hash function support by what the server also supports.
        ok-compression ifnot 40 fail-alert then
 
        \ Filter hash function support by what the server also supports.
-       \ If no common hash function remains, then ECDHE suites are not
-       \ possible.
+       \ If no common hash function remains with RSA and/or ECDSA, then
+       \ the corresponding ECDHE suites are not possible.
        supported-hash-functions drop 257 *
        addr-hashes get16 and dup addr-hashes set16
        supported-hash-functions drop 257 *
        addr-hashes get16 and dup addr-hashes set16
-       0<> { can-ecdhe }
+       \ In 'can-ecdhe', bit 12 is set if ECDHE_RSA is possible, bit 13 is
+       \ set if ECDHE_ECDSA is possible.
+       dup 0xFF and 0<> neg
+       swap 8 >> 0<> 2 and or { can-ecdhe }
 
        \ Filter supported curves. If there is no common curve between
        \ client and us, then ECDHE suites cannot be used. Note that we
 
        \ Filter supported curves. If there is no common curve between
        \ client and us, then ECDHE suites cannot be used. Note that we
@@ -684,6 +785,11 @@ cc: save-session ( -- ) {
        resume if -1 ret then
 
        \ We are not resuming, so a new session ID should be generated.
        resume if -1 ret then
 
        \ We are not resuming, so a new session ID should be generated.
+       \ We don't check that the new ID is distinct from the one sent
+       \ by the client because probability of such an event is 2^(-256),
+       \ i.e. much (much) lower than that of an undetected transmission
+       \ error or hardware miscomputation, and with similar consequences
+       \ (handshake simply fails).
        addr-session_id 32 mkrand
        32 addr-session_id_len set8
 
        addr-session_id 32 mkrand
        32 addr-session_id_len set8
 
@@ -692,14 +798,14 @@ cc: save-session ( -- ) {
        \ server preference order is enforced, and also in case some
        \ suites are filtered out. In particular:
        \ -- ECDHE suites are removed if there is no common hash function
        \ server preference order is enforced, and also in case some
        \ suites are filtered out. In particular:
        \ -- ECDHE suites are removed if there is no common hash function
-       \    (for signatures) or no common curve.
+       \    (for the relevant signature algorithm) or no common curve.
        \ -- TLS-1.2-only suites are removed if the negociated version is
        \    TLS-1.1 or lower.
        addr-client_suites dup >css-off
        begin dup css-max < while
                dup get16 dup cipher-suite-to-elements
        \ -- TLS-1.2-only suites are removed if the negociated version is
        \    TLS-1.1 or lower.
        addr-client_suites dup >css-off
        begin dup css-max < while
                dup get16 dup cipher-suite-to-elements
-               can-ecdhe ifnot
-                       dup 12 >> dup 1 = swap 2 = or if
+               dup 12 >> dup 1 = swap 2 = or if
+                       dup can-ecdhe and ifnot
                                2drop 0 dup
                        then
                then
                                2drop 0 dup
                        then
                then
@@ -791,63 +897,6 @@ cc: save-session ( -- ) {
                drop
        then ;
 
                drop
        then ;
 
-\ Compute total chain length. This includes the individual certificate
-\ headers, but not the total chain header. This also sets the cert_cur,
-\ cert_len and chain_len context fields.
-cc: total-chain-length ( -- len ) {
-       size_t u;
-       uint32_t total;
-
-       total = 0;
-       for (u = 0; u < CTX->chain_len; u ++) {
-               total += 3 + (uint32_t)CTX->chain[u].data_len;
-       }
-       T0_PUSH(total);
-}
-
-\ Get length for current certificate in the chain; if the chain end was
-\ reached, then this returns -1.
-cc: begin-cert ( -- len ) {
-       if (CTX->chain_len == 0) {
-               T0_PUSHi(-1);
-       } else {
-               CTX->cert_cur = CTX->chain->data;
-               CTX->cert_len = CTX->chain->data_len;
-               CTX->chain ++;
-               CTX->chain_len --;
-               T0_PUSH(CTX->cert_len);
-       }
-}
-
-\ Copy a chunk of certificate data into the pad. Returned value is the
-\ chunk length, or 0 if the certificate end is reached.
-cc: copy-cert-chunk ( -- len ) {
-       size_t clen;
-
-       clen = CTX->cert_len;
-       if (clen > sizeof ENG->pad) {
-               clen = sizeof ENG->pad;
-       }
-       memcpy(ENG->pad, CTX->cert_cur, clen);
-       CTX->cert_cur += clen;
-       CTX->cert_len -= clen;
-       T0_PUSH(clen);
-}
-
-\ Write the server Certificate.
-: write-Certificate ( -- )
-       11 write8
-       total-chain-length
-       dup 3 + write24 write24
-       begin
-               begin-cert
-               dup 0< if drop ret then write24
-               begin copy-cert-chunk dup while
-                       addr-pad swap write-blob
-               repeat
-               drop
-       again ;
-
 \ Do the first part of ECDHE. Returned value is the computed signature
 \ length, or a negative error code on error.
 cc: do-ecdhe-part1 ( curve -- len ) {
 \ Do the first part of ECDHE. Returned value is the computed signature
 \ length, or a negative error code on error.
 cc: do-ecdhe-part1 ( curve -- len ) {
@@ -900,6 +949,166 @@ cc: do-ecdhe-part1 ( curve -- len ) {
        sig-len write16
        addr-pad sig-len write-blob ;
 
        sig-len write16
        addr-pad sig-len write-blob ;
 
+\ Get length of the list of anchor names to send to the client. The length
+\ includes the per-name 2-byte header, but _not_ the 2-byte header for
+\ the list itself. If no client certificate is requested, then this
+\ returns 0.
+cc: ta-names-total-length ( -- len ) {
+       size_t u, len;
+
+       len = 0;
+       if (CTX->ta_names != NULL) {
+               for (u = 0; u < CTX->num_tas; u ++) {
+                       len += CTX->ta_names[u].len + 2;
+               }
+       } else if (CTX->tas != NULL) {
+               for (u = 0; u < CTX->num_tas; u ++) {
+                       len += CTX->tas[u].dn.len + 2;
+               }
+       }
+       T0_PUSH(len);
+}
+
+\ Compute length and optionally write the contents of the list of
+\ supported client authentication methods.
+: write-list-auth ( do_write -- len )
+       0
+       addr-cipher_suite get16 use-ecdh? if
+               2+ over if 65 write8 66 write8 then
+       then
+       supports-rsa-sign? if 1+ over if 1 write8 then then
+       supports-ecdsa? if 1+ over if 64 write8 then then
+       swap drop ;
+
+: write-signhash-inner2 ( dow algo hashes len id -- dow algo hashes len )
+       { id }
+       over 1 id << and ifnot ret then
+       2+
+       3 pick if id write8 2 pick write8 then ;
+
+: write-signhash-inner1 ( dow algo hashes -- dow len )
+       0
+       4 write-signhash-inner2
+       5 write-signhash-inner2
+       6 write-signhash-inner2
+       3 write-signhash-inner2
+       2 write-signhash-inner2
+       -rot 2drop ;
+
+\ Compute length and optionally write the contents of the list of
+\ supported sign+hash algorithms.
+: write-list-signhash ( do_write -- len )
+       0 { len }
+       \ If supporting neither RSA nor ECDSA in the engine, then we
+       \ will do only static ECDH, and thus we claim support for
+       \ everything (for the X.509 validator).
+       supports-rsa-sign? supports-ecdsa? or ifnot
+               1 0x7C write-signhash-inner1 >len
+               3 0x7C write-signhash-inner1 len +
+               swap drop ret
+       then
+       supports-rsa-sign? if
+               1 supported-hash-functions drop
+               write-signhash-inner1 >len
+       then
+       supports-ecdsa? if
+               3 supported-hash-functions drop
+               write-signhash-inner1 len + >len
+       then
+       drop len ;
+
+\ Initialise index for sending the list of anchor DN.
+cc: begin-ta-name-list ( -- ) {
+       CTX->cur_dn_index = 0;
+}
+
+\ Switch to next DN in the list. Returned value is the DN length, or -1
+\ if the end of the list was reached.
+cc: begin-ta-name ( -- len ) {
+       const br_x500_name *dn;
+       if (CTX->cur_dn_index >= CTX->num_tas) {
+               T0_PUSHi(-1);
+       } else {
+               if (CTX->ta_names == NULL) {
+                       dn = &CTX->tas[CTX->cur_dn_index].dn;
+               } else {
+                       dn = &CTX->ta_names[CTX->cur_dn_index];
+               }
+               CTX->cur_dn_index ++;
+               CTX->cur_dn = dn->data;
+               CTX->cur_dn_len = dn->len;
+               T0_PUSH(CTX->cur_dn_len);
+       }
+}
+
+\ Copy a chunk of the current DN into the pad. Returned value is the
+\ chunk length; this is 0 when the end of the current DN is reached.
+cc: copy-dn-chunk ( -- len ) {
+       size_t clen;
+
+       clen = CTX->cur_dn_len;
+       if (clen > sizeof ENG->pad) {
+               clen = sizeof ENG->pad;
+       }
+       memcpy(ENG->pad, CTX->cur_dn, clen);
+       CTX->cur_dn += clen;
+       CTX->cur_dn_len -= clen;
+       T0_PUSH(clen);
+}
+
+\ Write a CertificateRequest message.
+: write-CertificateRequest ( -- )
+       \ The list of client authentication types includes:
+       \    rsa_sign (1)
+       \    ecdsa_sign (64)
+       \    rsa_fixed_ecdh (65)
+       \    ecdsa_fixed_ecdh (66)
+       \ rsa_sign and ecdsa_sign require, respectively, RSA and ECDSA
+       \ support. Static ECDH requires that the cipher suite is ECDH.
+       \ When we ask for static ECDH, we always send both rsa_fixed_ecdh
+       \ and ecdsa_fixed_ecdh because what matters there is what the
+       \ X.509 engine may support, and we do not control that.
+       \
+       \ With TLS 1.2, we must also send a list of supported signature
+       \ and hash algorithms. That list is supposed to qualify both
+       \ the engine itself, and the X.509 validator, which are separate
+       \ in BearSSL. There again, we use the engine capabilities in that
+       \ list, and resort to a generic all-support list if only
+       \ static ECDH is accepted.
+       \
+       \ (In practice, client implementations tend to have at most one
+       \ or two certificates, and send the chain regardless of what
+       \ algorithms are used in it.)
+
+       0 write-list-auth
+       addr-version get16 0x0303 >= if
+               2+ 0 write-list-signhash +
+       then
+       ta-names-total-length + 3 +
+
+       \ Message header
+       13 write8 write24
+
+       \ List of authentication methods
+       0 write-list-auth write8 1 write-list-auth drop
+
+       \ For TLS 1.2+, list of sign+hash
+       addr-version get16 0x0303 >= if
+               0 write-list-signhash write16 1 write-list-signhash drop
+       then
+
+       \ Trust anchor names
+       ta-names-total-length write16
+       begin-ta-name-list
+       begin
+               begin-ta-name
+               dup 0< if drop ret then write16
+               begin copy-dn-chunk dup while
+                       addr-pad swap write-blob
+               repeat
+               drop
+       again ;
+
 \ Write the Server Hello Done message.
 : write-ServerHelloDone ( -- )
        14 write8 0 write24 ;
 \ Write the Server Hello Done message.
 : write-ServerHelloDone ( -- )
        14 write8 0 write24 ;
@@ -927,11 +1136,18 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
        do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
 }
 
        do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
 }
 
-\ Read the Client Key Exchange.
-: read-ClientKeyExchange ( -- )
-       \ Get header, and check message type.
-       read-handshake-header 16 = ifnot ERR_UNEXPECTED fail then
+\ Perform static ECDH. The point from the client is the public key
+\ extracted from its certificate.
+cc: do-static-ecdh ( prf_id -- ) {
+       do_static_ecdh(CTX, T0_POP());
+}
 
 
+\ Read a ClientKeyExchange header.
+: read-ClientKeyExchange-header ( -- len )
+       read-handshake-header 16 = ifnot ERR_UNEXPECTED fail then ;
+
+\ Read the Client Key Exchange contents (non-empty case).
+: read-ClientKeyExchange-contents ( lim -- )
        \ What we should get depends on the cipher suite.
        addr-cipher_suite get16 use-rsa-keyx? if
                \ RSA key exchange: we expect a RSA-encrypted value.
        \ What we should get depends on the cipher suite.
        addr-cipher_suite get16 use-rsa-keyx? if
                \ RSA key exchange: we expect a RSA-encrypted value.
@@ -951,6 +1167,116 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
        then
        close-elt ;
 
        then
        close-elt ;
 
+\ Read the Client Key Exchange (normal case).
+: read-ClientKeyExchange ( -- )
+       read-ClientKeyExchange-header
+       read-ClientKeyExchange-contents ;
+
+\ Obtain all possible hash values for handshake messages so far. This
+\ is done because we need the hash value for the CertificateVerify
+\ _before_ knowing which hash function will actually be used, as this
+\ information is obtained from decoding the message header itself.
+\ All hash values are stored in the pad (208 bytes in total).
+cc: compute-hash-CV ( -- ) {
+       int i;
+
+       for (i = 1; i <= 6; i ++) {
+               br_multihash_out(&ENG->mhash, i,
+                       ENG->pad + HASH_PAD_OFF[i - 1]);
+       }
+}
+
+\ Copy the proper hash value from the pad into the dedicated buffer.
+\ Returned value is true (-1) on success, false (0) on error (error
+\ being an unimplemented hash function). The id has already been verified
+\ to be either 0 (for MD5+SHA-1) or one of the SHA-* functions.
+cc: copy-hash-CV ( hash_id -- bool ) {
+       int id = T0_POP();
+       size_t off, len;
+
+       if (id == 0) {
+               off = 0;
+               len = 36;
+       } else {
+               if (br_multihash_getimpl(&ENG->mhash, id) == 0) {
+                       T0_PUSH(0);
+                       T0_RET();
+               }
+               off = HASH_PAD_OFF[id - 1];
+               len = HASH_PAD_OFF[id] - off;
+       }
+       memcpy(CTX->hash_CV, ENG->pad + off, len);
+       CTX->hash_CV_len = len;
+       CTX->hash_CV_id = id;
+       T0_PUSHi(-1);
+}
+
+\ Verify signature in CertificateVerify. Output is 0 on success, or a
+\ non-zero error code.
+cc: verify-CV-sig ( sig-len -- err ) {
+       int err;
+
+       err = verify_CV_sig(CTX, T0_POP());
+       T0_PUSHi(err);
+}
+
+\ Process static ECDH.
+: process-static-ECDH ( ktu -- )
+       \ Static ECDH is allowed only if the cipher suite uses ECDH, and
+       \ the client's public key has type EC and allows key exchange.
+       \ BR_KEYTYPE_KEYX is 0x10, and BR_KEYTYPE_EC is 2.
+       0x1F and 0x12 = ifnot ERR_WRONG_KEY_USAGE fail then
+       addr-cipher_suite get16
+       dup use-ecdh? ifnot ERR_UNEXPECTED fail then
+       prf-id
+       do-static-ecdh ;
+
+\ Read CertificateVerify header.
+: read-CertificateVerify-header ( -- lim )
+       compute-hash-CV
+       read-handshake-header 15 = ifnot ERR_UNEXPECTED fail then ;
+
+\ Read CertificateVerify. The client key type + usage is expected on the
+\ stack.
+: read-CertificateVerify ( ktu -- )
+       \ Check that the key allows for signatures.
+       dup 0x20 and ifnot ERR_WRONG_KEY_USAGE fail then
+       0x0F and { key-type }
+
+       \ Get header.
+       read-CertificateVerify-header
+
+       \ With TLS 1.2+, there is an explicit hash + signature indication,
+       \ which must be compatible with the key type.
+       addr-version get16 0x0303 >= if
+               \ Get hash function, then signature algorithm. The
+               \ signature algorithm is 1 (RSA) or 3 (ECDSA) while our
+               \ symbolic constants for key types are 1 (RSA) or 2 (EC).
+               read16
+               dup 0xFF and 1+ 1 >> key-type = ifnot
+                       ERR_BAD_SIGNATURE fail
+               then
+               8 >>
+
+               \ We support only SHA-1, SHA-224, SHA-256, SHA-384
+               \ and SHA-512. We explicitly reject MD5.
+               dup 2 < over 6 > or if ERR_INVALID_ALGORITHM fail then
+       else
+               \ With TLS 1.0 and 1.1, hash is MD5+SHA-1 (0) for RSA,
+               \ SHA-1 (2) for ECDSA.
+               key-type 0x01 = if 0 else 2 then
+       then
+       copy-hash-CV ifnot ERR_INVALID_ALGORITHM fail then
+
+       \ Read signature.
+       read16 dup { sig-len }
+       dup 512 > if ERR_LIMIT_EXCEEDED fail then
+       addr-pad swap read-blob
+       sig-len verify-CV-sig
+       dup if fail then drop
+
+       close-elt ;
+
 \ Send a HelloRequest.
 : send-HelloRequest ( -- )
        flush-record
 \ Send a HelloRequest.
 : send-HelloRequest ( -- )
        flush-record
@@ -974,11 +1300,54 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
        else
                \ Not a session resumption
                write-ServerHello
        else
                \ Not a session resumption
                write-ServerHello
-               write-Certificate
+               write-Certificate drop
                write-ServerKeyExchange
                write-ServerKeyExchange
+               ta-names-total-length if
+                       write-CertificateRequest
+               then
                write-ServerHelloDone
                flush-record
                write-ServerHelloDone
                flush-record
-               read-ClientKeyExchange
+
+               \ If we sent a CertificateRequest then we expect a
+               \ Certificate message.
+               ta-names-total-length if
+                       \ Read client certificate.
+                       0 read-Certificate
+
+                       choice
+                               dup 0< uf
+                                       \ Client certificate validation failed.
+                                       2 flag? ifnot neg fail then
+                                       drop
+                                       read-ClientKeyExchange
+                                       read-CertificateVerify-header
+                                       dup skip-blob drop
+                               enduf
+                               dup 0= uf
+                                       \ Client sent no certificate at all.
+                                       drop
+                                       2 flag? ifnot
+                                               ERR_NO_CLIENT_AUTH fail
+                                       then
+                                       read-ClientKeyExchange
+                               enduf
+
+                               \ Client certificate was validated.
+                               read-ClientKeyExchange-header
+                               dup ifnot
+                                       \ Empty ClientKeyExchange.
+                                       drop
+                                       process-static-ECDH
+                               else
+                                       read-ClientKeyExchange-contents
+                                       read-CertificateVerify
+                               then
+                       endchoice
+               else
+                       \ No client certificate request, we just expect
+                       \ a non-empty ClientKeyExchange.
+                       read-ClientKeyExchange
+               then
                0 read-CCS-Finished
                0 write-CCS-Finished
                save-session
                0 read-CCS-Finished
                0 write-CCS-Finished
                save-session
similarity index 99%
rename from src/ssl/ssl_single_ec.c
rename to src/ssl/ssl_scert_single_ec.c
index 4edaca3..2648670 100644 (file)
@@ -36,7 +36,7 @@ se_choose(const br_ssl_server_policy_class **pctx,
 
        pc = (br_ssl_server_policy_ec_context *)pctx;
        st = br_ssl_server_get_client_suites(cc, &st_num);
 
        pc = (br_ssl_server_policy_ec_context *)pctx;
        st = br_ssl_server_get_client_suites(cc, &st_num);
-       hash_id = br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc));
+       hash_id = br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc) >> 8);
        if (cc->eng.session.version < BR_TLS12) {
                hash_id = br_sha1_ID;
        }
        if (cc->eng.session.version < BR_TLS12) {
                hash_id = br_sha1_ID;
        }
index f00c32b..7674f3f 100644 (file)
 /* see bearssl_x509.h */
 void
 br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
 /* see bearssl_x509.h */
 void
 br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
-       const br_rsa_public_key *pk)
+       const br_rsa_public_key *pk, unsigned usages)
 {
        ctx->vtable = &br_x509_knownkey_vtable;
        ctx->pkey.key_type = BR_KEYTYPE_RSA;
        ctx->pkey.key.rsa = *pk;
 {
        ctx->vtable = &br_x509_knownkey_vtable;
        ctx->pkey.key_type = BR_KEYTYPE_RSA;
        ctx->pkey.key.rsa = *pk;
+       ctx->usages = usages;
 }
 
 /* see bearssl_x509.h */
 void
 br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
 }
 
 /* see bearssl_x509.h */
 void
 br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
-       const br_ec_public_key *pk)
+       const br_ec_public_key *pk, unsigned usages)
 {
        ctx->vtable = &br_x509_knownkey_vtable;
        ctx->pkey.key_type = BR_KEYTYPE_EC;
        ctx->pkey.key.ec = *pk;
 {
        ctx->vtable = &br_x509_knownkey_vtable;
        ctx->pkey.key_type = BR_KEYTYPE_EC;
        ctx->pkey.key.ec = *pk;
+       ctx->usages = usages;
 }
 
 static void
 }
 
 static void
-kk_start_chain(const br_x509_class **ctx,
-       unsigned expected_key_type, const char *server_name)
+kk_start_chain(const br_x509_class **ctx, const char *server_name)
 {
        (void)ctx;
 {
        (void)ctx;
-       (void)expected_key_type;
        (void)server_name;
 }
 
        (void)server_name;
 }
 
@@ -82,9 +82,15 @@ kk_end_chain(const br_x509_class **ctx)
 }
 
 static const br_x509_pkey *
 }
 
 static const br_x509_pkey *
-kk_get_pkey(const br_x509_class *const *ctx)
+kk_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
 {
 {
-       return &((const br_x509_knownkey_context *)ctx)->pkey;
+       const br_x509_knownkey_context *xc;
+
+       xc = (const br_x509_knownkey_context *)ctx;
+       if (usages != NULL) {
+               *usages = xc->usages;
+       }
+       return &xc->pkey;
 }
 
 /* see bearssl_x509.h */
 }
 
 /* see bearssl_x509.h */
index 55d9e23..d022b00 100644 (file)
@@ -239,8 +239,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,
 }
 
 static void
 }
 
 static void
-xm_start_chain(const br_x509_class **ctx,
-       unsigned expected_key_type, const char *server_name)
+xm_start_chain(const br_x509_class **ctx, const char *server_name)
 {
        br_x509_minimal_context *cc;
 
 {
        br_x509_minimal_context *cc;
 
@@ -251,7 +250,6 @@ xm_start_chain(const br_x509_class **ctx,
        cc->cpu.dp = cc->dp_stack;
        cc->cpu.rp = cc->rp_stack;
        br_x509_minimal_init_main(&cc->cpu);
        cc->cpu.dp = cc->dp_stack;
        cc->cpu.rp = cc->rp_stack;
        br_x509_minimal_init_main(&cc->cpu);
-       cc->expected_key_type = expected_key_type;
        if (server_name == NULL || *server_name == 0) {
                cc->server_name = NULL;
        } else {
        if (server_name == NULL || *server_name == 0) {
                cc->server_name = NULL;
        } else {
@@ -320,7 +318,7 @@ xm_end_chain(const br_x509_class **ctx)
 }
 
 static const br_x509_pkey *
 }
 
 static const br_x509_pkey *
-xm_get_pkey(const br_x509_class *const *ctx)
+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
 {
        br_x509_minimal_context *cc;
 
 {
        br_x509_minimal_context *cc;
 
@@ -328,6 +326,9 @@ xm_get_pkey(const br_x509_class *const *ctx)
        if (cc->err == BR_ERR_X509_OK
                || cc->err == BR_ERR_X509_NOT_TRUSTED)
        {
        if (cc->err == BR_ERR_X509_OK
                || cc->err == BR_ERR_X509_NOT_TRUSTED)
        {
+               if (usages != NULL) {
+                       *usages = cc->key_usages;
+               }
                return &((br_x509_minimal_context *)ctx)->pkey;
        } else {
                return NULL;
                return &((br_x509_minimal_context *)ctx)->pkey;
        } else {
                return NULL;
@@ -518,7 +519,6 @@ static const uint8_t t0_codeblock[] = {
        T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,
        T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01,
-       T0_INT1(BR_ERR_X509_WRONG_KEY_TYPE), 0x00, 0x00, 0x01,
        T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),
        0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00,
        T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),
        0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00,
        0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00,
@@ -527,182 +527,182 @@ static const uint8_t t0_codeblock[] = {
        0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00,
        0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00,
-       0x01, T0_INT2(offsetof(CONTEXT_NAME, expected_key_type)), 0x00, 0x00,
-       0x01, T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01,
+       0x01, T0_INT2(offsetof(CONTEXT_NAME, key_usages)), 0x00, 0x00, 0x01,
+       T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01,
        T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01,
        T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01,
        T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01,
-       T0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0x81, 0x31,
-       0x6E, 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00,
+       T0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0x81, 0x2F,
+       0x6C, 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00,
        0x00, 0x01, 0x81, 0x02, 0x00, 0x00, 0x01, 0x82, 0x08, 0x00, 0x00, 0x01,
        0x81, 0x70, 0x00, 0x00, 0x01, 0x81, 0x64, 0x00, 0x04, 0x03, 0x00, 0x03,
        0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07,
        0x02, 0x02, 0x02, 0x00, 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D,
        0x00, 0x01, 0x81, 0x02, 0x00, 0x00, 0x01, 0x82, 0x08, 0x00, 0x00, 0x01,
        0x81, 0x70, 0x00, 0x00, 0x01, 0x81, 0x64, 0x00, 0x04, 0x03, 0x00, 0x03,
        0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07,
        0x02, 0x02, 0x02, 0x00, 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D,
-       0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x23, 0x02, 0x01, 0x13, 0x39, 0x02,
-       0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, 0x4F, 0x26, 0x00, 0x00, 0x06,
-       0x02, 0x50, 0x26, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x00, 0x11, 0x05,
-       0x02, 0x53, 0x26, 0x70, 0x00, 0x00, 0x11, 0x05, 0x02, 0x53, 0x26, 0x71,
-       0x00, 0x00, 0x06, 0x02, 0x49, 0x26, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00,
-       0x00, 0x23, 0x1E, 0x01, 0x08, 0x0E, 0x39, 0x3D, 0x1E, 0x09, 0x00, 0x09,
-       0x03, 0x00, 0x59, 0x29, 0x81, 0x1D, 0x37, 0x81, 0x1D, 0x81, 0x20, 0x23,
-       0x01, 0x20, 0x11, 0x06, 0x15, 0x22, 0x70, 0x81, 0x1B, 0x81, 0x20, 0x01,
-       0x02, 0x74, 0x81, 0x1E, 0x01, 0x02, 0x12, 0x06, 0x02, 0x54, 0x26, 0x75,
-       0x81, 0x20, 0x01, 0x02, 0x74, 0x81, 0x1C, 0x81, 0x1D, 0x81, 0x2A, 0x81,
-       0x10, 0x63, 0x5F, 0x1F, 0x16, 0x81, 0x1D, 0x81, 0x15, 0x27, 0x67, 0x06,
-       0x02, 0x48, 0x26, 0x81, 0x15, 0x27, 0x6E, 0x06, 0x02, 0x48, 0x26, 0x75,
-       0x81, 0x10, 0x02, 0x00, 0x06, 0x05, 0x2B, 0x03, 0x01, 0x04, 0x08, 0x5F,
-       0x66, 0x1F, 0x25, 0x05, 0x02, 0x47, 0x26, 0x66, 0x63, 0x1F, 0x16, 0x81,
-       0x1D, 0x81, 0x1D, 0x81, 0x11, 0x05, 0x02, 0x54, 0x26, 0x81, 0x24, 0x24,
-       0x06, 0x2C, 0x81, 0x2A, 0x81, 0x12, 0x81, 0x1D, 0x61, 0x81, 0x18, 0x03,
-       0x03, 0x61, 0x39, 0x02, 0x03, 0x09, 0x39, 0x02, 0x03, 0x0A, 0x81, 0x18,
-       0x03, 0x04, 0x75, 0x62, 0x28, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, 0x12,
-       0x06, 0x02, 0x55, 0x26, 0x75, 0x58, 0x03, 0x02, 0x04, 0x3E, 0x81, 0x01,
-       0x24, 0x06, 0x37, 0x81, 0x11, 0x05, 0x02, 0x54, 0x26, 0x68, 0x24, 0x06,
-       0x04, 0x01, 0x17, 0x04, 0x12, 0x69, 0x24, 0x06, 0x04, 0x01, 0x18, 0x04,
-       0x0A, 0x6A, 0x24, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x54, 0x26, 0x03,
-       0x05, 0x75, 0x81, 0x12, 0x23, 0x03, 0x06, 0x23, 0x61, 0x32, 0x0D, 0x06,
-       0x02, 0x4D, 0x26, 0x81, 0x13, 0x57, 0x03, 0x02, 0x04, 0x02, 0x54, 0x26,
-       0x75, 0x02, 0x00, 0x06, 0x33, 0x60, 0x2A, 0x01, 0x0F, 0x15, 0x23, 0x06,
-       0x09, 0x02, 0x02, 0x11, 0x05, 0x02, 0x56, 0x26, 0x04, 0x01, 0x22, 0x02,
-       0x02, 0x58, 0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02, 0x04, 0x1D,
-       0x04, 0x10, 0x57, 0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05, 0x02, 0x06,
-       0x1C, 0x04, 0x03, 0x54, 0x26, 0x22, 0x04, 0x24, 0x02, 0x02, 0x58, 0x2E,
-       0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02, 0x04, 0x21, 0x04, 0x10, 0x57,
-       0x2E, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05, 0x02, 0x06, 0x20, 0x04, 0x03,
-       0x54, 0x26, 0x22, 0x23, 0x06, 0x01, 0x26, 0x22, 0x01, 0x00, 0x03, 0x07,
-       0x81, 0x21, 0x01, 0x21, 0x81, 0x07, 0x01, 0x22, 0x81, 0x07, 0x23, 0x01,
-       0x23, 0x11, 0x06, 0x81, 0x36, 0x22, 0x70, 0x81, 0x1B, 0x81, 0x1D, 0x23,
-       0x06, 0x81, 0x28, 0x01, 0x00, 0x03, 0x08, 0x81, 0x1D, 0x81, 0x11, 0x22,
-       0x81, 0x20, 0x23, 0x01, 0x01, 0x11, 0x06, 0x06, 0x81, 0x14, 0x03, 0x08,
-       0x81, 0x20, 0x01, 0x04, 0x74, 0x81, 0x1B, 0x6D, 0x24, 0x06, 0x11, 0x02,
-       0x00, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x06, 0x81, 0x0E, 0x01, 0x7F, 0x03,
-       0x07, 0x04, 0x80, 0x72, 0x81, 0x09, 0x24, 0x06, 0x07, 0x02, 0x00, 0x81,
-       0x0F, 0x04, 0x80, 0x66, 0x81, 0x2D, 0x24, 0x06, 0x13, 0x02, 0x00, 0x06,
-       0x0A, 0x01, 0x00, 0x03, 0x01, 0x81, 0x0D, 0x03, 0x01, 0x04, 0x02, 0x81,
-       0x2B, 0x04, 0x80, 0x4E, 0x6C, 0x24, 0x06, 0x05, 0x81, 0x2B, 0x04, 0x80,
-       0x45, 0x81, 0x30, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x3C, 0x81, 0x08,
-       0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x33, 0x81, 0x2E, 0x24, 0x06, 0x04,
-       0x81, 0x2B, 0x04, 0x2A, 0x76, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x22,
-       0x81, 0x00, 0x24, 0x06, 0x04, 0x81, 0x2B, 0x04, 0x19, 0x6B, 0x24, 0x06,
-       0x04, 0x81, 0x2B, 0x04, 0x11, 0x81, 0x2F, 0x24, 0x06, 0x04, 0x81, 0x2B,
-       0x04, 0x08, 0x02, 0x08, 0x06, 0x02, 0x46, 0x26, 0x81, 0x2B, 0x75, 0x75,
-       0x04, 0xFE, 0x54, 0x75, 0x75, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02,
-       0x53, 0x26, 0x22, 0x75, 0x38, 0x02, 0x00, 0x06, 0x08, 0x02, 0x01, 0x3A,
-       0x2D, 0x05, 0x02, 0x42, 0x26, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00,
-       0x02, 0x07, 0x2D, 0x05, 0x02, 0x4E, 0x26, 0x81, 0x20, 0x72, 0x81, 0x1B,
-       0x81, 0x11, 0x06, 0x81, 0x07, 0x81, 0x25, 0x24, 0x06, 0x08, 0x01, 0x02,
-       0x58, 0x81, 0x02, 0x04, 0x80, 0x6C, 0x81, 0x26, 0x24, 0x06, 0x08, 0x01,
-       0x03, 0x58, 0x81, 0x03, 0x04, 0x80, 0x5F, 0x81, 0x27, 0x24, 0x06, 0x08,
-       0x01, 0x04, 0x58, 0x81, 0x04, 0x04, 0x80, 0x52, 0x81, 0x28, 0x24, 0x06,
-       0x08, 0x01, 0x05, 0x58, 0x81, 0x05, 0x04, 0x80, 0x45, 0x81, 0x29, 0x24,
-       0x06, 0x07, 0x01, 0x06, 0x58, 0x81, 0x06, 0x04, 0x39, 0x7B, 0x24, 0x06,
-       0x07, 0x01, 0x02, 0x57, 0x81, 0x02, 0x04, 0x2E, 0x7C, 0x24, 0x06, 0x07,
-       0x01, 0x03, 0x57, 0x81, 0x03, 0x04, 0x23, 0x7D, 0x24, 0x06, 0x07, 0x01,
-       0x04, 0x57, 0x81, 0x04, 0x04, 0x18, 0x7E, 0x24, 0x06, 0x07, 0x01, 0x05,
-       0x57, 0x81, 0x05, 0x04, 0x0D, 0x7F, 0x24, 0x06, 0x07, 0x01, 0x06, 0x57,
-       0x81, 0x06, 0x04, 0x02, 0x54, 0x26, 0x5C, 0x33, 0x5E, 0x35, 0x1B, 0x23,
-       0x05, 0x02, 0x54, 0x26, 0x5B, 0x35, 0x04, 0x02, 0x54, 0x26, 0x81, 0x2A,
-       0x81, 0x12, 0x23, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02,
-       0x4D, 0x26, 0x23, 0x5D, 0x33, 0x5A, 0x81, 0x13, 0x75, 0x75, 0x01, 0x00,
-       0x59, 0x34, 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x23, 0x01, 0x00, 0x01,
-       0x09, 0x6F, 0x05, 0x02, 0x45, 0x26, 0x00, 0x00, 0x2E, 0x2E, 0x00, 0x00,
-       0x01, 0x81, 0x08, 0x00, 0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81,
-       0x19, 0x00, 0x00, 0x01, 0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00,
-       0x00, 0x01, 0x82, 0x04, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01,
-       0x3D, 0x00, 0x00, 0x01, 0x80, 0x43, 0x00, 0x00, 0x01, 0x80, 0x4D, 0x00,
-       0x00, 0x01, 0x80, 0x57, 0x00, 0x00, 0x01, 0x80, 0x61, 0x00, 0x00, 0x2E,
-       0x11, 0x06, 0x07, 0x3F, 0x81, 0x1B, 0x81, 0x2A, 0x81, 0x21, 0x00, 0x00,
-       0x01, 0x81, 0x78, 0x00, 0x00, 0x01, 0x81, 0x68, 0x00, 0x00, 0x01, 0x7F,
-       0x78, 0x19, 0x01, 0x00, 0x78, 0x19, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x34,
-       0x00, 0x01, 0x7A, 0x0D, 0x06, 0x02, 0x4C, 0x26, 0x23, 0x03, 0x00, 0x0A,
-       0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x81, 0x1D, 0x23, 0x06,
-       0x18, 0x81, 0x20, 0x01, 0x22, 0x11, 0x06, 0x0C, 0x71, 0x81, 0x1F, 0x22,
-       0x2B, 0x02, 0x00, 0x2D, 0x03, 0x00, 0x04, 0x03, 0x22, 0x81, 0x1C, 0x04,
-       0x65, 0x75, 0x02, 0x00, 0x00, 0x00, 0x81, 0x1D, 0x81, 0x21, 0x23, 0x01,
-       0x01, 0x11, 0x06, 0x0A, 0x81, 0x14, 0x05, 0x02, 0x4E, 0x26, 0x81, 0x21,
-       0x04, 0x02, 0x4E, 0x26, 0x23, 0x01, 0x02, 0x11, 0x06, 0x0E, 0x22, 0x71,
-       0x81, 0x1E, 0x64, 0x29, 0x3E, 0x0D, 0x06, 0x02, 0x4E, 0x26, 0x81, 0x21,
-       0x01, 0x7F, 0x10, 0x06, 0x02, 0x53, 0x26, 0x22, 0x75, 0x00, 0x02, 0x06,
-       0x10, 0x60, 0x2A, 0x01, 0x10, 0x15, 0x06, 0x04, 0x01, 0x30, 0x04, 0x03,
-       0x01, 0x81, 0x40, 0x04, 0x02, 0x01, 0x04, 0x03, 0x00, 0x81, 0x20, 0x01,
-       0x03, 0x74, 0x81, 0x1B, 0x81, 0x22, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07,
-       0x12, 0x06, 0x02, 0x53, 0x26, 0x23, 0x01, 0x00, 0x2E, 0x11, 0x06, 0x05,
-       0x22, 0x4A, 0x26, 0x04, 0x17, 0x01, 0x01, 0x2E, 0x11, 0x06, 0x0B, 0x22,
-       0x81, 0x22, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E, 0x04, 0x06, 0x22, 0x81,
-       0x22, 0x01, 0x00, 0x22, 0x02, 0x00, 0x15, 0x05, 0x02, 0x4A, 0x26, 0x81,
-       0x2A, 0x00, 0x02, 0x36, 0x01, 0x00, 0x65, 0x35, 0x81, 0x1D, 0x23, 0x06,
-       0x80, 0x6F, 0x81, 0x20, 0x01, 0x11, 0x73, 0x81, 0x1B, 0x23, 0x05, 0x02,
-       0x41, 0x26, 0x23, 0x06, 0x80, 0x5B, 0x81, 0x1D, 0x81, 0x20, 0x01, 0x06,
-       0x74, 0x81, 0x1B, 0x23, 0x01, 0x03, 0x11, 0x06, 0x1E, 0x81, 0x22, 0x01,
-       0x10, 0x0E, 0x03, 0x00, 0x81, 0x22, 0x01, 0x08, 0x0E, 0x02, 0x00, 0x09,
-       0x03, 0x00, 0x81, 0x22, 0x02, 0x00, 0x09, 0x01, 0x82, 0xD4, 0x88, 0x03,
-       0x11, 0x03, 0x01, 0x81, 0x2A, 0x02, 0x01, 0x06, 0x23, 0x81, 0x20, 0x23,
-       0x23, 0x01, 0x0C, 0x11, 0x39, 0x01, 0x13, 0x11, 0x2D, 0x39, 0x01, 0x14,
-       0x11, 0x2D, 0x06, 0x07, 0x71, 0x81, 0x1F, 0x22, 0x75, 0x04, 0x07, 0x22,
-       0x01, 0x00, 0x65, 0x35, 0x81, 0x2A, 0x04, 0x02, 0x81, 0x2A, 0x04, 0xFF,
-       0x21, 0x75, 0x04, 0xFF, 0x0D, 0x75, 0x1A, 0x00, 0x00, 0x81, 0x20, 0x01,
-       0x06, 0x74, 0x81, 0x1F, 0x00, 0x00, 0x81, 0x20, 0x01, 0x03, 0x74, 0x81,
-       0x1B, 0x81, 0x22, 0x06, 0x02, 0x52, 0x26, 0x00, 0x00, 0x39, 0x23, 0x06,
-       0x07, 0x2F, 0x23, 0x06, 0x01, 0x19, 0x04, 0x76, 0x3F, 0x00, 0x00, 0x01,
-       0x01, 0x74, 0x81, 0x1A, 0x01, 0x01, 0x10, 0x06, 0x02, 0x40, 0x26, 0x81,
-       0x22, 0x3B, 0x00, 0x04, 0x81, 0x20, 0x23, 0x01, 0x17, 0x01, 0x18, 0x6F,
-       0x05, 0x02, 0x45, 0x26, 0x01, 0x18, 0x11, 0x03, 0x00, 0x71, 0x81, 0x1B,
-       0x81, 0x16, 0x02, 0x00, 0x06, 0x0D, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01,
-       0x81, 0x16, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x23, 0x01, 0x32, 0x0D, 0x06,
-       0x04, 0x01, 0x80, 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02,
-       0x01, 0x01, 0x82, 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04,
-       0x0C, 0x09, 0x02, 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C,
-       0x0A, 0x02, 0x01, 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09,
-       0x03, 0x03, 0x01, 0x01, 0x01, 0x0C, 0x81, 0x17, 0x3E, 0x01, 0x01, 0x0E,
-       0x02, 0x01, 0x01, 0x04, 0x07, 0x3C, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07,
-       0x3B, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3C, 0x2D, 0x15, 0x06, 0x03,
-       0x01, 0x18, 0x09, 0x81, 0x0B, 0x09, 0x77, 0x23, 0x01, 0x05, 0x14, 0x02,
-       0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x39, 0x81, 0x17,
-       0x02, 0x03, 0x09, 0x3E, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0x81, 0x17,
-       0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0x81, 0x17,
-       0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C,
-       0x81, 0x17, 0x02, 0x02, 0x09, 0x03, 0x02, 0x81, 0x22, 0x23, 0x01, 0x2E,
-       0x11, 0x06, 0x0E, 0x22, 0x81, 0x22, 0x23, 0x01, 0x30, 0x01, 0x39, 0x6F,
-       0x06, 0x03, 0x22, 0x04, 0x73, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x45,
-       0x26, 0x75, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0x81, 0x22, 0x79, 0x01,
-       0x0A, 0x08, 0x03, 0x00, 0x81, 0x22, 0x79, 0x02, 0x00, 0x09, 0x00, 0x02,
-       0x03, 0x00, 0x03, 0x01, 0x81, 0x16, 0x23, 0x02, 0x01, 0x02, 0x00, 0x6F,
-       0x05, 0x02, 0x45, 0x26, 0x00, 0x00, 0x32, 0x81, 0x20, 0x01, 0x02, 0x74,
-       0x0B, 0x81, 0x19, 0x00, 0x03, 0x23, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
-       0x81, 0x1B, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x51,
-       0x26, 0x23, 0x01, 0x00, 0x11, 0x06, 0x0C, 0x22, 0x23, 0x05, 0x04, 0x22,
-       0x01, 0x00, 0x00, 0x81, 0x22, 0x04, 0x6E, 0x02, 0x01, 0x23, 0x05, 0x02,
-       0x4D, 0x26, 0x3E, 0x03, 0x01, 0x02, 0x02, 0x35, 0x02, 0x02, 0x3D, 0x03,
-       0x02, 0x23, 0x06, 0x04, 0x81, 0x22, 0x04, 0x67, 0x22, 0x02, 0x00, 0x02,
-       0x01, 0x0A, 0x00, 0x01, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x0D, 0x06,
-       0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x23, 0x05, 0x02, 0x4B, 0x26, 0x03,
-       0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x1A, 0x02, 0x00,
-       0x3E, 0x03, 0x00, 0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02,
-       0x4C, 0x26, 0x01, 0x08, 0x0E, 0x39, 0x81, 0x22, 0x32, 0x09, 0x04, 0x5F,
-       0x00, 0x00, 0x81, 0x1A, 0x81, 0x0C, 0x00, 0x00, 0x81, 0x1B, 0x81, 0x2A,
-       0x00, 0x00, 0x81, 0x20, 0x72, 0x81, 0x1B, 0x00, 0x01, 0x81, 0x1B, 0x23,
-       0x05, 0x02, 0x51, 0x26, 0x81, 0x22, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06,
-       0x02, 0x51, 0x26, 0x03, 0x00, 0x23, 0x06, 0x17, 0x81, 0x22, 0x02, 0x00,
-       0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x51, 0x26, 0x01,
-       0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x66, 0x22, 0x02, 0x00, 0x00, 0x00,
-       0x81, 0x1B, 0x23, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x09, 0x81, 0x2A, 0x01,
-       0x00, 0x65, 0x35, 0x01, 0x00, 0x00, 0x23, 0x65, 0x35, 0x65, 0x3D, 0x81,
-       0x13, 0x01, 0x7F, 0x00, 0x01, 0x81, 0x22, 0x03, 0x00, 0x02, 0x00, 0x01,
-       0x05, 0x14, 0x01, 0x01, 0x15, 0x2C, 0x02, 0x00, 0x01, 0x06, 0x14, 0x23,
-       0x01, 0x01, 0x15, 0x06, 0x02, 0x43, 0x26, 0x01, 0x04, 0x0E, 0x02, 0x00,
-       0x01, 0x1F, 0x15, 0x23, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x44, 0x26, 0x09,
-       0x00, 0x00, 0x23, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x81, 0x20,
-       0x00, 0x00, 0x23, 0x05, 0x02, 0x4C, 0x26, 0x3E, 0x81, 0x23, 0x00, 0x00,
-       0x30, 0x23, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x22, 0x19, 0x04, 0x74,
-       0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00,
-       0x00, 0x01, 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00,
-       0x00, 0x81, 0x2B, 0x22, 0x00, 0x00, 0x23, 0x06, 0x08, 0x81, 0x2C, 0x23,
-       0x06, 0x01, 0x19, 0x04, 0x75, 0x00, 0x00, 0x01, 0x00, 0x2E, 0x2F, 0x0B,
-       0x3F, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x01, 0x81, 0x7C, 0x00,
-       0x00, 0x01, 0x82, 0x11, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x01,
-       0x03, 0x31, 0x01, 0x03, 0x31, 0x00
+       0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x23, 0x02, 0x01, 0x13, 0x38, 0x02,
+       0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, 0x4E, 0x26, 0x00, 0x00, 0x06,
+       0x02, 0x4F, 0x26, 0x00, 0x00, 0x01, 0x10, 0x71, 0x00, 0x00, 0x11, 0x05,
+       0x02, 0x52, 0x26, 0x6E, 0x00, 0x00, 0x11, 0x05, 0x02, 0x52, 0x26, 0x6F,
+       0x00, 0x00, 0x06, 0x02, 0x48, 0x26, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00,
+       0x00, 0x23, 0x1E, 0x01, 0x08, 0x0E, 0x38, 0x3C, 0x1E, 0x09, 0x00, 0x09,
+       0x03, 0x00, 0x57, 0x29, 0x81, 0x1B, 0x36, 0x81, 0x1B, 0x81, 0x1E, 0x23,
+       0x01, 0x20, 0x11, 0x06, 0x15, 0x22, 0x6E, 0x81, 0x19, 0x81, 0x1E, 0x01,
+       0x02, 0x72, 0x81, 0x1C, 0x01, 0x02, 0x12, 0x06, 0x02, 0x53, 0x26, 0x73,
+       0x81, 0x1E, 0x01, 0x02, 0x72, 0x81, 0x1A, 0x81, 0x1B, 0x81, 0x28, 0x81,
+       0x0E, 0x61, 0x5D, 0x1F, 0x16, 0x81, 0x1B, 0x81, 0x13, 0x27, 0x65, 0x06,
+       0x02, 0x47, 0x26, 0x81, 0x13, 0x27, 0x6C, 0x06, 0x02, 0x47, 0x26, 0x73,
+       0x81, 0x0E, 0x02, 0x00, 0x06, 0x05, 0x2A, 0x03, 0x01, 0x04, 0x08, 0x5D,
+       0x64, 0x1F, 0x25, 0x05, 0x02, 0x46, 0x26, 0x64, 0x61, 0x1F, 0x16, 0x81,
+       0x1B, 0x81, 0x1B, 0x81, 0x0F, 0x05, 0x02, 0x53, 0x26, 0x81, 0x22, 0x24,
+       0x06, 0x2C, 0x81, 0x28, 0x81, 0x10, 0x81, 0x1B, 0x5F, 0x81, 0x16, 0x03,
+       0x03, 0x5F, 0x38, 0x02, 0x03, 0x09, 0x38, 0x02, 0x03, 0x0A, 0x81, 0x16,
+       0x03, 0x04, 0x73, 0x60, 0x28, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, 0x12,
+       0x06, 0x02, 0x54, 0x26, 0x73, 0x56, 0x03, 0x02, 0x04, 0x3D, 0x7F, 0x24,
+       0x06, 0x37, 0x81, 0x0F, 0x05, 0x02, 0x53, 0x26, 0x66, 0x24, 0x06, 0x04,
+       0x01, 0x17, 0x04, 0x12, 0x67, 0x24, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A,
+       0x68, 0x24, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x53, 0x26, 0x03, 0x05,
+       0x73, 0x81, 0x10, 0x23, 0x03, 0x06, 0x23, 0x5F, 0x31, 0x0D, 0x06, 0x02,
+       0x4C, 0x26, 0x81, 0x11, 0x55, 0x03, 0x02, 0x04, 0x02, 0x53, 0x26, 0x73,
+       0x02, 0x00, 0x06, 0x21, 0x02, 0x02, 0x56, 0x2D, 0x11, 0x06, 0x08, 0x22,
+       0x02, 0x03, 0x02, 0x04, 0x1D, 0x04, 0x10, 0x55, 0x2D, 0x11, 0x06, 0x08,
+       0x22, 0x02, 0x05, 0x02, 0x06, 0x1C, 0x04, 0x03, 0x53, 0x26, 0x22, 0x04,
+       0x24, 0x02, 0x02, 0x56, 0x2D, 0x11, 0x06, 0x08, 0x22, 0x02, 0x03, 0x02,
+       0x04, 0x21, 0x04, 0x10, 0x55, 0x2D, 0x11, 0x06, 0x08, 0x22, 0x02, 0x05,
+       0x02, 0x06, 0x20, 0x04, 0x03, 0x53, 0x26, 0x22, 0x23, 0x06, 0x01, 0x26,
+       0x22, 0x01, 0x00, 0x03, 0x07, 0x81, 0x1F, 0x01, 0x21, 0x81, 0x05, 0x01,
+       0x22, 0x81, 0x05, 0x23, 0x01, 0x23, 0x11, 0x06, 0x81, 0x35, 0x22, 0x6E,
+       0x81, 0x19, 0x81, 0x1B, 0x23, 0x06, 0x81, 0x27, 0x01, 0x00, 0x03, 0x08,
+       0x81, 0x1B, 0x81, 0x0F, 0x22, 0x81, 0x1E, 0x23, 0x01, 0x01, 0x11, 0x06,
+       0x06, 0x81, 0x12, 0x03, 0x08, 0x81, 0x1E, 0x01, 0x04, 0x72, 0x81, 0x19,
+       0x6B, 0x24, 0x06, 0x11, 0x02, 0x00, 0x06, 0x04, 0x81, 0x29, 0x04, 0x06,
+       0x81, 0x0C, 0x01, 0x7F, 0x03, 0x07, 0x04, 0x80, 0x71, 0x81, 0x07, 0x24,
+       0x06, 0x07, 0x02, 0x00, 0x81, 0x0D, 0x04, 0x80, 0x65, 0x81, 0x2B, 0x24,
+       0x06, 0x13, 0x02, 0x00, 0x06, 0x0A, 0x01, 0x00, 0x03, 0x01, 0x81, 0x0B,
+       0x03, 0x01, 0x04, 0x02, 0x81, 0x29, 0x04, 0x80, 0x4D, 0x6A, 0x24, 0x06,
+       0x05, 0x81, 0x29, 0x04, 0x80, 0x44, 0x81, 0x2E, 0x24, 0x06, 0x04, 0x81,
+       0x29, 0x04, 0x3B, 0x81, 0x06, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x32,
+       0x81, 0x2C, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x29, 0x74, 0x24, 0x06,
+       0x04, 0x81, 0x29, 0x04, 0x21, 0x7E, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04,
+       0x19, 0x69, 0x24, 0x06, 0x04, 0x81, 0x29, 0x04, 0x11, 0x81, 0x2D, 0x24,
+       0x06, 0x04, 0x81, 0x29, 0x04, 0x08, 0x02, 0x08, 0x06, 0x02, 0x45, 0x26,
+       0x81, 0x29, 0x73, 0x73, 0x04, 0xFE, 0x55, 0x73, 0x73, 0x04, 0x08, 0x01,
+       0x7F, 0x11, 0x05, 0x02, 0x52, 0x26, 0x22, 0x73, 0x37, 0x02, 0x00, 0x06,
+       0x08, 0x02, 0x01, 0x39, 0x2C, 0x05, 0x02, 0x41, 0x26, 0x02, 0x00, 0x06,
+       0x01, 0x17, 0x02, 0x00, 0x02, 0x07, 0x2C, 0x05, 0x02, 0x4D, 0x26, 0x81,
+       0x1E, 0x70, 0x81, 0x19, 0x81, 0x0F, 0x06, 0x81, 0x07, 0x81, 0x23, 0x24,
+       0x06, 0x08, 0x01, 0x02, 0x56, 0x81, 0x00, 0x04, 0x80, 0x6C, 0x81, 0x24,
+       0x24, 0x06, 0x08, 0x01, 0x03, 0x56, 0x81, 0x01, 0x04, 0x80, 0x5F, 0x81,
+       0x25, 0x24, 0x06, 0x08, 0x01, 0x04, 0x56, 0x81, 0x02, 0x04, 0x80, 0x52,
+       0x81, 0x26, 0x24, 0x06, 0x08, 0x01, 0x05, 0x56, 0x81, 0x03, 0x04, 0x80,
+       0x45, 0x81, 0x27, 0x24, 0x06, 0x07, 0x01, 0x06, 0x56, 0x81, 0x04, 0x04,
+       0x39, 0x79, 0x24, 0x06, 0x07, 0x01, 0x02, 0x55, 0x81, 0x00, 0x04, 0x2E,
+       0x7A, 0x24, 0x06, 0x07, 0x01, 0x03, 0x55, 0x81, 0x01, 0x04, 0x23, 0x7B,
+       0x24, 0x06, 0x07, 0x01, 0x04, 0x55, 0x81, 0x02, 0x04, 0x18, 0x7C, 0x24,
+       0x06, 0x07, 0x01, 0x05, 0x55, 0x81, 0x03, 0x04, 0x0D, 0x7D, 0x24, 0x06,
+       0x07, 0x01, 0x06, 0x55, 0x81, 0x04, 0x04, 0x02, 0x53, 0x26, 0x5A, 0x32,
+       0x5C, 0x34, 0x1B, 0x23, 0x05, 0x02, 0x53, 0x26, 0x59, 0x34, 0x04, 0x02,
+       0x53, 0x26, 0x81, 0x28, 0x81, 0x10, 0x23, 0x01,
+       T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x4C, 0x26, 0x23, 0x5B,
+       0x32, 0x58, 0x81, 0x11, 0x73, 0x73, 0x01, 0x00, 0x57, 0x33, 0x18, 0x00,
+       0x00, 0x01, 0x30, 0x0A, 0x23, 0x01, 0x00, 0x01, 0x09, 0x6D, 0x05, 0x02,
+       0x44, 0x26, 0x00, 0x00, 0x2D, 0x2D, 0x00, 0x00, 0x01, 0x81, 0x08, 0x00,
+       0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81, 0x19, 0x00, 0x00, 0x01,
+       0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00, 0x00, 0x01, 0x82, 0x04,
+       0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00, 0x01,
+       0x80, 0x43, 0x00, 0x00, 0x01, 0x80, 0x4D, 0x00, 0x00, 0x01, 0x80, 0x57,
+       0x00, 0x00, 0x01, 0x80, 0x61, 0x00, 0x00, 0x2D, 0x11, 0x06, 0x07, 0x3E,
+       0x81, 0x19, 0x81, 0x28, 0x81, 0x1F, 0x00, 0x00, 0x01, 0x81, 0x78, 0x00,
+       0x00, 0x01, 0x81, 0x68, 0x00, 0x00, 0x01, 0x30, 0x5E, 0x34, 0x01, 0x7F,
+       0x76, 0x19, 0x01, 0x00, 0x76, 0x19, 0x04, 0x7A, 0x00, 0x01, 0x81, 0x34,
+       0x00, 0x01, 0x78, 0x0D, 0x06, 0x02, 0x4B, 0x26, 0x23, 0x03, 0x00, 0x0A,
+       0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x81, 0x1B, 0x23, 0x06,
+       0x18, 0x81, 0x1E, 0x01, 0x22, 0x11, 0x06, 0x0C, 0x6F, 0x81, 0x1D, 0x22,
+       0x2A, 0x02, 0x00, 0x2C, 0x03, 0x00, 0x04, 0x03, 0x22, 0x81, 0x1A, 0x04,
+       0x65, 0x73, 0x02, 0x00, 0x00, 0x00, 0x81, 0x1B, 0x81, 0x1F, 0x23, 0x01,
+       0x01, 0x11, 0x06, 0x0A, 0x81, 0x12, 0x05, 0x02, 0x4D, 0x26, 0x81, 0x1F,
+       0x04, 0x02, 0x4D, 0x26, 0x23, 0x01, 0x02, 0x11, 0x06, 0x0E, 0x22, 0x6F,
+       0x81, 0x1C, 0x62, 0x29, 0x3D, 0x0D, 0x06, 0x02, 0x4D, 0x26, 0x81, 0x1F,
+       0x01, 0x7F, 0x10, 0x06, 0x02, 0x52, 0x26, 0x22, 0x73, 0x00, 0x02, 0x03,
+       0x00, 0x81, 0x1E, 0x01, 0x03, 0x72, 0x81, 0x19, 0x81, 0x20, 0x03, 0x01,
+       0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02, 0x52, 0x26, 0x23, 0x01, 0x00,
+       0x2D, 0x11, 0x06, 0x05, 0x22, 0x49, 0x26, 0x04, 0x17, 0x01, 0x01, 0x2D,
+       0x11, 0x06, 0x0B, 0x22, 0x81, 0x20, 0x02, 0x01, 0x14, 0x02, 0x01, 0x0E,
+       0x04, 0x06, 0x22, 0x81, 0x20, 0x01, 0x00, 0x22, 0x02, 0x00, 0x06, 0x19,
+       0x01, 0x00, 0x2D, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01, 0x10, 0x2C, 0x38,
+       0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2C, 0x5E, 0x34, 0x04,
+       0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x49, 0x26, 0x81, 0x28, 0x00, 0x02,
+       0x35, 0x01, 0x00, 0x63, 0x34, 0x81, 0x1B, 0x23, 0x06, 0x80, 0x6F, 0x81,
+       0x1E, 0x01, 0x11, 0x71, 0x81, 0x19, 0x23, 0x05, 0x02, 0x40, 0x26, 0x23,
+       0x06, 0x80, 0x5B, 0x81, 0x1B, 0x81, 0x1E, 0x01, 0x06, 0x72, 0x81, 0x19,
+       0x23, 0x01, 0x03, 0x11, 0x06, 0x1E, 0x81, 0x20, 0x01, 0x10, 0x0E, 0x03,
+       0x00, 0x81, 0x20, 0x01, 0x08, 0x0E, 0x02, 0x00, 0x09, 0x03, 0x00, 0x81,
+       0x20, 0x02, 0x00, 0x09, 0x01, 0x82, 0xD4, 0x88, 0x03, 0x11, 0x03, 0x01,
+       0x81, 0x28, 0x02, 0x01, 0x06, 0x23, 0x81, 0x1E, 0x23, 0x23, 0x01, 0x0C,
+       0x11, 0x38, 0x01, 0x13, 0x11, 0x2C, 0x38, 0x01, 0x14, 0x11, 0x2C, 0x06,
+       0x07, 0x6F, 0x81, 0x1D, 0x22, 0x73, 0x04, 0x07, 0x22, 0x01, 0x00, 0x63,
+       0x34, 0x81, 0x28, 0x04, 0x02, 0x81, 0x28, 0x04, 0xFF, 0x21, 0x73, 0x04,
+       0xFF, 0x0D, 0x73, 0x1A, 0x00, 0x00, 0x81, 0x1E, 0x01, 0x06, 0x72, 0x81,
+       0x1D, 0x00, 0x00, 0x81, 0x1E, 0x01, 0x03, 0x72, 0x81, 0x19, 0x81, 0x20,
+       0x06, 0x02, 0x51, 0x26, 0x00, 0x00, 0x38, 0x23, 0x06, 0x07, 0x2E, 0x23,
+       0x06, 0x01, 0x19, 0x04, 0x76, 0x3E, 0x00, 0x00, 0x01, 0x01, 0x72, 0x81,
+       0x18, 0x01, 0x01, 0x10, 0x06, 0x02, 0x3F, 0x26, 0x81, 0x20, 0x3A, 0x00,
+       0x04, 0x81, 0x1E, 0x23, 0x01, 0x17, 0x01, 0x18, 0x6D, 0x05, 0x02, 0x44,
+       0x26, 0x01, 0x18, 0x11, 0x03, 0x00, 0x6F, 0x81, 0x19, 0x81, 0x14, 0x02,
+       0x00, 0x06, 0x0D, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0x81, 0x14, 0x02,
+       0x01, 0x09, 0x04, 0x0E, 0x23, 0x01, 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80,
+       0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02, 0x01, 0x01, 0x82,
+       0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02,
+       0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01,
+       0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01,
+       0x01, 0x01, 0x0C, 0x81, 0x15, 0x3D, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01,
+       0x04, 0x07, 0x3B, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x3A, 0x02, 0x01,
+       0x01, 0x83, 0x10, 0x07, 0x3B, 0x2C, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09,
+       0x81, 0x09, 0x09, 0x75, 0x23, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03,
+       0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x38, 0x81, 0x15, 0x02, 0x03, 0x09,
+       0x3D, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0x81, 0x15, 0x01, 0x9C, 0x10,
+       0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0x81, 0x15, 0x01, 0x3C, 0x08,
+       0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0x81, 0x15, 0x02,
+       0x02, 0x09, 0x03, 0x02, 0x81, 0x20, 0x23, 0x01, 0x2E, 0x11, 0x06, 0x0E,
+       0x22, 0x81, 0x20, 0x23, 0x01, 0x30, 0x01, 0x39, 0x6D, 0x06, 0x03, 0x22,
+       0x04, 0x73, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x44, 0x26, 0x73, 0x02,
+       0x03, 0x02, 0x02, 0x00, 0x01, 0x81, 0x20, 0x77, 0x01, 0x0A, 0x08, 0x03,
+       0x00, 0x81, 0x20, 0x77, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03,
+       0x01, 0x81, 0x14, 0x23, 0x02, 0x01, 0x02, 0x00, 0x6D, 0x05, 0x02, 0x44,
+       0x26, 0x00, 0x00, 0x31, 0x81, 0x1E, 0x01, 0x02, 0x72, 0x0B, 0x81, 0x17,
+       0x00, 0x03, 0x23, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x81, 0x19, 0x81,
+       0x20, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x50, 0x26, 0x23, 0x01,
+       0x00, 0x11, 0x06, 0x0C, 0x22, 0x23, 0x05, 0x04, 0x22, 0x01, 0x00, 0x00,
+       0x81, 0x20, 0x04, 0x6E, 0x02, 0x01, 0x23, 0x05, 0x02, 0x4C, 0x26, 0x3D,
+       0x03, 0x01, 0x02, 0x02, 0x34, 0x02, 0x02, 0x3C, 0x03, 0x02, 0x23, 0x06,
+       0x04, 0x81, 0x20, 0x04, 0x67, 0x22, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00,
+       0x01, 0x81, 0x20, 0x23, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01,
+       0x81, 0x00, 0x0A, 0x23, 0x05, 0x02, 0x4A, 0x26, 0x03, 0x00, 0x01, 0x00,
+       0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x1A, 0x02, 0x00, 0x3D, 0x03, 0x00,
+       0x23, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4B, 0x26, 0x01,
+       0x08, 0x0E, 0x38, 0x81, 0x20, 0x31, 0x09, 0x04, 0x5F, 0x00, 0x00, 0x81,
+       0x18, 0x81, 0x0A, 0x00, 0x00, 0x81, 0x19, 0x81, 0x28, 0x00, 0x00, 0x81,
+       0x1E, 0x70, 0x81, 0x19, 0x00, 0x01, 0x81, 0x19, 0x23, 0x05, 0x02, 0x50,
+       0x26, 0x81, 0x20, 0x23, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x50, 0x26,
+       0x03, 0x00, 0x23, 0x06, 0x17, 0x81, 0x20, 0x02, 0x00, 0x23, 0x01, 0x87,
+       0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x50, 0x26, 0x01, 0x08, 0x0E, 0x09,
+       0x03, 0x00, 0x04, 0x66, 0x22, 0x02, 0x00, 0x00, 0x00, 0x81, 0x19, 0x23,
+       0x01, 0x81, 0x7F, 0x12, 0x06, 0x09, 0x81, 0x28, 0x01, 0x00, 0x63, 0x34,
+       0x01, 0x00, 0x00, 0x23, 0x63, 0x34, 0x63, 0x3C, 0x81, 0x11, 0x01, 0x7F,
+       0x00, 0x01, 0x81, 0x20, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05, 0x14, 0x01,
+       0x01, 0x15, 0x2B, 0x02, 0x00, 0x01, 0x06, 0x14, 0x23, 0x01, 0x01, 0x15,
+       0x06, 0x02, 0x42, 0x26, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01, 0x1F, 0x15,
+       0x23, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x43, 0x26, 0x09, 0x00, 0x00, 0x23,
+       0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x81, 0x1E, 0x00, 0x00, 0x23,
+       0x05, 0x02, 0x4B, 0x26, 0x3D, 0x81, 0x21, 0x00, 0x00, 0x2F, 0x23, 0x01,
+       0x00, 0x13, 0x06, 0x01, 0x00, 0x22, 0x19, 0x04, 0x74, 0x00, 0x01, 0x01,
+       0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x1F,
+       0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x81, 0x29,
+       0x22, 0x00, 0x00, 0x23, 0x06, 0x08, 0x81, 0x2A, 0x23, 0x06, 0x01, 0x19,
+       0x04, 0x75, 0x00, 0x00, 0x01, 0x00, 0x2D, 0x2E, 0x0B, 0x3E, 0x00, 0x00,
+       0x01, 0x81, 0x6C, 0x00, 0x00, 0x01, 0x81, 0x7C, 0x00, 0x00, 0x01, 0x82,
+       0x11, 0x00, 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x01, 0x03, 0x30, 0x01,
+       0x03, 0x30, 0x00
 };
 
 static const uint16_t t0_caddr[] = {
 };
 
 static const uint16_t t0_caddr[] = {
@@ -736,98 +736,97 @@ static const uint16_t t0_caddr[] = {
        112,
        116,
        120,
        112,
        116,
        120,
-       124,
-       129,
-       134,
-       139,
-       144,
-       149,
-       154,
-       159,
-       164,
-       172,
-       177,
-       182,
-       187,
-       192,
-       197,
-       202,
-       207,
-       212,
-       217,
-       222,
-       227,
-       232,
-       261,
-       276,
-       282,
-       288,
-       293,
-       301,
-       309,
-       315,
-       320,
-       331,
+       125,
+       130,
+       135,
+       140,
+       145,
+       150,
+       155,
+       160,
+       168,
+       173,
+       178,
+       183,
+       188,
+       193,
+       198,
+       203,
+       208,
+       213,
+       218,
+       223,
+       228,
+       257,
+       272,
+       278,
+       284,
+       289,
+       297,
+       305,
+       311,
+       316,
+       327,
+       1029,
+       1044,
+       1048,
        1053,
        1053,
+       1058,
+       1063,
        1068,
        1068,
-       1072,
-       1077,
-       1082,
+       1073,
+       1078,
+       1083,
        1087,
        1092,
        1097,
        1102,
        1107,
        1087,
        1092,
        1097,
        1102,
        1107,
-       1111,
-       1116,
-       1121,
-       1126,
-       1131,
-       1144,
-       1149,
-       1154,
-       1165,
-       1170,
-       1184,
-       1222,
-       1275,
-       1363,
-       1489,
-       1498,
-       1513,
-       1527,
-       1544,
-       1776,
-       1792,
+       1120,
+       1125,
+       1130,
+       1145,
+       1150,
+       1164,
+       1202,
+       1255,
+       1352,
+       1478,
+       1487,
+       1502,
+       1516,
+       1533,
+       1765,
+       1781,
+       1799,
        1810,
        1810,
-       1821,
-       1892,
-       1950,
-       1956,
-       1962,
-       1969,
-       2020,
-       2049,
-       2094,
-       2106,
-       2116,
-       2129,
-       2133,
-       2137,
-       2141,
-       2145,
-       2149,
-       2153,
-       2158,
-       2171,
-       2179,
-       2184,
-       2189,
-       2194,
-       2199
+       1881,
+       1939,
+       1945,
+       1951,
+       1958,
+       2009,
+       2038,
+       2083,
+       2095,
+       2105,
+       2118,
+       2122,
+       2126,
+       2130,
+       2134,
+       2138,
+       2142,
+       2147,
+       2160,
+       2168,
+       2173,
+       2178,
+       2183,
+       2188
 };
 
 };
 
-#define T0_INTERPRETED   59
+#define T0_INTERPRETED   58
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
 
 #define T0_ENTER(ip, rp, slot)   do { \
                const unsigned char *t0_newip; \
@@ -848,7 +847,7 @@ name(void *ctx) \
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
        T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
 }
 
-T0_DEFENTRY(br_x509_minimal_init_main, 138)
+T0_DEFENTRY(br_x509_minimal_init_main, 136)
 
 void
 br_x509_minimal_run(void *t0ctx)
 
 void
 br_x509_minimal_run(void *t0ctx)
@@ -1100,7 +1099,7 @@ br_x509_minimal_run(void *t0ctx)
                if (ta->flags & BR_X509_TA_CA) {
                        continue;
                }
                if (ta->flags & BR_X509_TA_CA) {
                        continue;
                }
-               hash_dn(CTX, ta->dn, ta->dn_len, hashed_DN);
+               hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
                if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
                        continue;
                }
                if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
                        continue;
                }
@@ -1161,7 +1160,7 @@ br_x509_minimal_run(void *t0ctx)
                if (!(ta->flags & BR_X509_TA_CA)) {
                        continue;
                }
                if (!(ta->flags & BR_X509_TA_CA)) {
                        continue;
                }
-               hash_dn(CTX, ta->dn, ta->dn_len, hashed_DN);
+               hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
                if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
                        continue;
                }
                if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
                        continue;
                }
@@ -1360,14 +1359,6 @@ br_x509_minimal_run(void *t0ctx)
                                }
                                break;
                        case 42: {
                                }
                                break;
                        case 42: {
-                               /* get8 */
-
-       uint32_t addr = T0_POP();
-       T0_PUSH(*((unsigned char *)CTX + addr));
-
-                               }
-                               break;
-                       case 43: {
                                /* match-server-name */
 
        size_t n1, n2;
                                /* match-server-name */
 
        size_t n1, n2;
@@ -1402,7 +1393,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 44: {
+                       case 43: {
                                /* neg */
 
        uint32_t a = T0_POP();
                                /* neg */
 
        uint32_t a = T0_POP();
@@ -1410,7 +1401,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 45: {
+                       case 44: {
                                /* or */
 
        uint32_t b = T0_POP();
                                /* or */
 
        uint32_t b = T0_POP();
@@ -1419,12 +1410,12 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 46: {
+                       case 45: {
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
                                /* over */
  T0_PUSH(T0_PEEK(1)); 
                                }
                                break;
-                       case 47: {
+                       case 46: {
                                /* read-blob-inner */
 
        uint32_t len = T0_POP();
                                /* read-blob-inner */
 
        uint32_t len = T0_POP();
@@ -1450,7 +1441,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 48: {
+                       case 47: {
                                /* read8-low */
 
        if (CTX->hlen == 0) {
                                /* read8-low */
 
        if (CTX->hlen == 0) {
@@ -1469,17 +1460,17 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 49: {
+                       case 48: {
                                /* roll */
  T0_ROLL(T0_POP()); 
                                }
                                break;
                                /* roll */
  T0_ROLL(T0_POP()); 
                                }
                                break;
-                       case 50: {
+                       case 49: {
                                /* rot */
  T0_ROT(); 
                                }
                                break;
                                /* rot */
  T0_ROT(); 
                                }
                                break;
-                       case 51: {
+                       case 50: {
                                /* set16 */
 
        uint32_t addr = T0_POP();
                                /* set16 */
 
        uint32_t addr = T0_POP();
@@ -1487,7 +1478,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 52: {
+                       case 51: {
                                /* set32 */
 
        uint32_t addr = T0_POP();
                                /* set32 */
 
        uint32_t addr = T0_POP();
@@ -1495,7 +1486,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 53: {
+                       case 52: {
                                /* set8 */
 
        uint32_t addr = T0_POP();
                                /* set8 */
 
        uint32_t addr = T0_POP();
@@ -1503,7 +1494,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 54: {
+                       case 53: {
                                /* start-dn-hash */
 
        CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
                                /* start-dn-hash */
 
        CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
@@ -1511,7 +1502,7 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 55: {
+                       case 54: {
                                /* start-tbs-hash */
 
        br_multihash_init(&CTX->mhash);
                                /* start-tbs-hash */
 
        br_multihash_init(&CTX->mhash);
@@ -1519,19 +1510,19 @@ br_x509_minimal_run(void *t0ctx)
 
                                }
                                break;
 
                                }
                                break;
-                       case 56: {
+                       case 55: {
                                /* stop-tbs-hash */
 
        CTX->do_mhash = 0;
 
                                }
                                break;
                                /* stop-tbs-hash */
 
        CTX->do_mhash = 0;
 
                                }
                                break;
-                       case 57: {
+                       case 56: {
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
                                /* swap */
  T0_SWAP(); 
                                }
                                break;
-                       case 58: {
+                       case 57: {
                                /* zero-server-name */
 
        T0_PUSHi(-(CTX->server_name == NULL));
                                /* zero-server-name */
 
        T0_PUSHi(-(CTX->server_name == NULL));
index bdb3e18..385972b 100644 (file)
@@ -188,8 +188,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,
 }
 
 static void
 }
 
 static void
-xm_start_chain(const br_x509_class **ctx,
-       unsigned expected_key_type, const char *server_name)
+xm_start_chain(const br_x509_class **ctx, const char *server_name)
 {
        br_x509_minimal_context *cc;
 
 {
        br_x509_minimal_context *cc;
 
@@ -200,7 +199,6 @@ xm_start_chain(const br_x509_class **ctx,
        cc->cpu.dp = cc->dp_stack;
        cc->cpu.rp = cc->rp_stack;
        br_x509_minimal_init_main(&cc->cpu);
        cc->cpu.dp = cc->dp_stack;
        cc->cpu.rp = cc->rp_stack;
        br_x509_minimal_init_main(&cc->cpu);
-       cc->expected_key_type = expected_key_type;
        if (server_name == NULL || *server_name == 0) {
                cc->server_name = NULL;
        } else {
        if (server_name == NULL || *server_name == 0) {
                cc->server_name = NULL;
        } else {
@@ -269,7 +267,7 @@ xm_end_chain(const br_x509_class **ctx)
 }
 
 static const br_x509_pkey *
 }
 
 static const br_x509_pkey *
-xm_get_pkey(const br_x509_class *const *ctx)
+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
 {
        br_x509_minimal_context *cc;
 
 {
        br_x509_minimal_context *cc;
 
@@ -277,6 +275,9 @@ xm_get_pkey(const br_x509_class *const *ctx)
        if (cc->err == BR_ERR_X509_OK
                || cc->err == BR_ERR_X509_NOT_TRUSTED)
        {
        if (cc->err == BR_ERR_X509_OK
                || cc->err == BR_ERR_X509_NOT_TRUSTED)
        {
+               if (usages != NULL) {
+                       *usages = cc->key_usages;
+               }
                return &((br_x509_minimal_context *)ctx)->pkey;
        } else {
                return NULL;
                return &((br_x509_minimal_context *)ctx)->pkey;
        } else {
                return NULL;
@@ -472,7 +473,7 @@ cc: zero-server-name ( -- bool ) {
        T0_PUSHi(-(CTX->server_name == NULL));
 }
 
        T0_PUSHi(-(CTX->server_name == NULL));
 }
 
-addr: expected_key_type
+addr: key_usages
 addr: cert_sig
 addr: cert_sig_len
 addr: cert_signer_key_type
 addr: cert_sig
 addr: cert_sig_len
 addr: cert_signer_key_type
@@ -705,7 +706,7 @@ cc: check-direct-trust ( -- ) {
                if (ta->flags & BR_X509_TA_CA) {
                        continue;
                }
                if (ta->flags & BR_X509_TA_CA) {
                        continue;
                }
-               hash_dn(CTX, ta->dn, ta->dn_len, hashed_DN);
+               hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
                if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
                        continue;
                }
                if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
                        continue;
                }
@@ -765,7 +766,7 @@ cc: check-trust-anchor-CA ( -- ) {
                if (!(ta->flags & BR_X509_TA_CA)) {
                        continue;
                }
                if (!(ta->flags & BR_X509_TA_CA)) {
                        continue;
                }
-               hash_dn(CTX, ta->dn, ta->dn_len, hashed_DN);
+               hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
                if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
                        continue;
                }
                if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
                        continue;
                }
@@ -892,20 +893,14 @@ OID: subjectInfoAccess             1.3.6.1.5.5.7.1.11
 
 \ Process a Key Usage extension.
 \ For the EE certificate:
 
 \ Process a Key Usage extension.
 \ For the EE certificate:
-\   -- if the expected key usage is "key exchange", then the extension
-\      must contain either keyEncipherment (2) or dataEncipherment (3);
-\   -- if the expected key usage is "signature", then the extension
-\      must contain either digitalSignature (0) or nonRepudiation (1).
+\   -- if the key usage contains keyEncipherment (2), dataEncipherment (3)
+\      or keyAgreement (4), then the "key exchange" usage is allowed;
+\   -- if the key usage contains digitalSignature (0) or nonRepudiation (1),
+\      then the "signature" usage is allowed.
 \ For CA certificates, the extension must contain keyCertSign (5).
 : process-keyUsage ( lim ee -- lim )
 \ For CA certificates, the extension must contain keyCertSign (5).
 : process-keyUsage ( lim ee -- lim )
-       \ Compute flags, depending on EE status and expected key usage.
-       \ This is a mask of bits in the first byte.
-       if
-               addr-expected_key_type get8 0x10 and if 0x30 else 0xC0 then
-       else
-               0x04
-       then
-       { mask }
+       { ee }
+
        \ Read tag for the BIT STRING and open it.
        read-tag 0x03 check-tag-primitive
        read-length-open-elt
        \ Read tag for the BIT STRING and open it.
        read-tag 0x03 check-tag-primitive
        read-length-open-elt
@@ -919,7 +914,20 @@ OID: subjectInfoAccess             1.3.6.1.5.5.7.1.11
                1 of read8 ign >> ign << endof
                drop read8 0
        endcase
                1 of read8 ign >> ign << endof
                drop read8 0
        endcase
-       mask and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then
+
+       \ Check bits.
+       ee if
+               \ EE: get usages.
+               0
+               over 0x38 and if 0x10 or then
+               swap 0xC0 and if 0x20 or then
+               addr-key_usages set8
+       else
+               \ Not EE: keyCertSign must be set.
+               0x04 and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then
+       then
+
+       \ We don't care about subsequent bytes.
        skip-close-elt ;
 
 \ Process a Subject Alt Name extension. Returned value is a boolean set
        skip-close-elt ;
 
 \ Process a Subject Alt Name extension. Returned value is a boolean set
@@ -1070,15 +1078,8 @@ OID: subjectInfoAccess             1.3.6.1.5.5.7.1.11
 
        \ Process public key.
        ee if
 
        \ Process public key.
        ee if
-               \ For the EE certificate, check that the key type
-               \ matches that which was expected, then copy the
-               \ data to the relevant buffer.
-               addr-expected_key_type get8 0x0F and
-               dup if
-                       pkey-type = ifnot ERR_X509_WRONG_KEY_TYPE fail then
-               else
-                       drop
-               then
+               \ For the EE certificate, copy the key data to the
+               \ relevant buffer.
                pkey-type case
                        KEYTYPE_RSA of nlen elen copy-ee-rsa-pkey endof
                        KEYTYPE_EC of curve qlen copy-ee-ec-pkey endof
                pkey-type case
                        KEYTYPE_RSA of nlen elen copy-ee-rsa-pkey endof
                        KEYTYPE_EC of curve qlen copy-ee-ec-pkey endof
@@ -1286,6 +1287,9 @@ OID: subjectInfoAccess             1.3.6.1.5.5.7.1.11
        check-trust-anchor-CA ;
 
 : main
        check-trust-anchor-CA ;
 
 : main
+       \ Unless restricted by a Key Usage extension, all usages are
+       \ deemed allowed.
+       0x30 addr-key_usages set8
        -1 decode-certificate
        co
        begin
        -1 decode-certificate
        co
        begin
index 52a9e2c..c4f0885 100644 (file)
@@ -1438,6 +1438,7 @@ run_test_case(test_case *tc)
        blob *certs;
        br_x509_pkey *ee_pkey_ref;
        const br_x509_pkey *ee_pkey;
        blob *certs;
        br_x509_pkey *ee_pkey_ref;
        const br_x509_pkey *ee_pkey;
+       unsigned usages;
        unsigned status;
 
        printf("%s: ", tc->name);
        unsigned status;
 
        printf("%s: ", tc->name);
@@ -1477,8 +1478,8 @@ run_test_case(test_case *tc)
                                tta->key_name);
                        exit(EXIT_FAILURE);
                }
                                tta->key_name);
                        exit(EXIT_FAILURE);
                }
-               anchors[u].dn = tta->dn;
-               anchors[u].dn_len = tta->dn_len;
+               anchors[u].dn.data = tta->dn;
+               anchors[u].dn.len = tta->dn_len;
                anchors[u].flags = tta->flags;
                anchors[u].pkey = *tak;
        }
                anchors[u].flags = tta->flags;
                anchors[u].pkey = *tak;
        }
@@ -1541,8 +1542,7 @@ run_test_case(test_case *tc)
         * Run the engine. We inject certificates by chunks of 100 bytes
         * in order to exercise the coroutine API.
         */
         * Run the engine. We inject certificates by chunks of 100 bytes
         * in order to exercise the coroutine API.
         */
-       ctx.vtable->start_chain(&ctx.vtable,
-               tc->key_type_usage, tc->servername);
+       ctx.vtable->start_chain(&ctx.vtable, tc->servername);
        for (u = 0; u < num_certs; u ++) {
                size_t v;
 
        for (u = 0; u < num_certs; u ++) {
                size_t v;
 
@@ -1561,7 +1561,22 @@ run_test_case(test_case *tc)
                ctx.vtable->end_cert(&ctx.vtable);
        }
        status = ctx.vtable->end_chain(&ctx.vtable);
                ctx.vtable->end_cert(&ctx.vtable);
        }
        status = ctx.vtable->end_chain(&ctx.vtable);
-       ee_pkey = ctx.vtable->get_pkey(&ctx.vtable);
+       ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
+
+       /*
+        * Check key type and usage.
+        */
+       if (ee_pkey != NULL) {
+               unsigned ktu;
+
+               ktu = ee_pkey->key_type | usages;
+               if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
+                       fprintf(stderr, "wrong key type + usage"
+                               " (expected 0x%02X, got 0x%02X)\n",
+                               tc->key_type_usage, ktu);
+                       exit(EXIT_FAILURE);
+               }
+       }
 
        /*
         * Check results. Note that we may still get a public key if
 
        /*
         * Check results. Note that we may still get a public key if
index a3ceb14..e93ed4c 100644 (file)
@@ -279,6 +279,11 @@ void list_names(void);
  */
 const char *ec_curve_name(int curve);
 
  */
 const char *ec_curve_name(int curve);
 
+/*
+ * Get the symbolic name for a hash function name (by ID).
+ */
+const char *hash_function_name(int id);
+
 /*
  * Read a file completely. The returned block is allocated with xmalloc()
  * and must be released by the caller.
 /*
  * Read a file completely. The returned block is allocated with xmalloc()
  * and must be released by the caller.
@@ -342,6 +347,12 @@ pem_object *decode_pem(const void *src, size_t len, size_t *num);
  */
 br_x509_certificate *read_certificates(const char *fname, size_t *num);
 
  */
 br_x509_certificate *read_certificates(const char *fname, size_t *num);
 
+/*
+ * Release certificates. This releases all certificate data arrays,
+ * and the whole array as well.
+ */
+void free_certificates(br_x509_certificate *certs, size_t num);
+
 /*
  * Interpret a certificate as a trust anchor. The trust anchor is
  * newly allocated with xmalloc() and the caller must release it.
 /*
  * Interpret a certificate as a trust anchor. The trust anchor is
  * newly allocated with xmalloc() and the caller must release it.
@@ -369,6 +380,12 @@ void free_ta_contents(br_x509_trust_anchor *ta);
  */
 size_t read_trust_anchors(anchor_list *dst, const char *fname);
 
  */
 size_t read_trust_anchors(anchor_list *dst, const char *fname);
 
+/*
+ * Get the "signer key type" for the certificate (key type of the
+ * issuing CA). On error, this prints a message on stderr, and returns 0.
+ */
+int get_cert_signer_algo(br_x509_certificate *xc);
+
 /*
  * Special "no anchor" X.509 validator that wraps around another X.509
  * validator and turns "not trusted" error codes into success. This is
 /*
  * Special "no anchor" X.509 validator that wraps around another X.509
  * validator and turns "not trusted" error codes into success. This is
@@ -408,6 +425,20 @@ private_key *read_private_key(const char *fname);
  */
 void free_private_key(private_key *sk);
 
  */
 void free_private_key(private_key *sk);
 
+/*
+ * Get the encoded OID for a given hash function (to use with PKCS#1
+ * signatures). If the hash function ID is 0 (for MD5+SHA-1), or if
+ * the ID is not one of the SHA-* functions (SHA-1, SHA-224, SHA-256,
+ * SHA-384, SHA-512), then this function returns NULL.
+ */
+const unsigned char *get_hash_oid(int id);
+
+/*
+ * Get a hash implementation by ID. This returns NULL if the hash
+ * implementation is not available.
+ */
+const br_hash_class *get_hash_impl(int id);
+
 /*
  * Find the symbolic name and the description for an error. If 'err' is
  * recognised then the error symbolic name is returned; if 'comment' is
 /*
  * Find the symbolic name and the description for an error. If 'err' is
  * recognised then the error symbolic name is returned; if 'comment' is
index fdee5c6..91ca9b9 100644 (file)
@@ -53,8 +53,8 @@ certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
                VEC_CLEAR(vdn);
                return -1;
        }
                VEC_CLEAR(vdn);
                return -1;
        }
-       ta->dn = VEC_TOARRAY(vdn);
-       ta->dn_len = VEC_LEN(vdn);
+       ta->dn.data = VEC_TOARRAY(vdn);
+       ta->dn.len = VEC_LEN(vdn);
        VEC_CLEAR(vdn);
        ta->flags = 0;
        if (br_x509_decoder_isCA(&dc)) {
        VEC_CLEAR(vdn);
        ta->flags = 0;
        if (br_x509_decoder_isCA(&dc)) {
@@ -76,7 +76,7 @@ certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
                break;
        default:
                fprintf(stderr, "ERROR: unsupported public key type in CA\n");
                break;
        default:
                fprintf(stderr, "ERROR: unsupported public key type in CA\n");
-               xfree(ta->dn);
+               xfree(ta->dn.data);
                return -1;
        }
        return 0;
                return -1;
        }
        return 0;
@@ -99,7 +99,7 @@ certificate_to_trust_anchor(br_x509_certificate *xc)
 void
 free_ta_contents(br_x509_trust_anchor *ta)
 {
 void
 free_ta_contents(br_x509_trust_anchor *ta)
 {
-       xfree(ta->dn);
+       xfree(ta->dn.data);
        switch (ta->pkey.key_type) {
        case BR_KEYTYPE_RSA:
                xfree(ta->pkey.key.rsa.n);
        switch (ta->pkey.key_type) {
        case BR_KEYTYPE_RSA:
                xfree(ta->pkey.key.rsa.n);
@@ -137,15 +137,32 @@ read_trust_anchors(anchor_list *dst, const char *fname)
        return num;
 }
 
        return num;
 }
 
+/* see brssl.h */
+int
+get_cert_signer_algo(br_x509_certificate *xc)
+{
+       br_x509_decoder_context dc;
+       int err;
+
+       br_x509_decoder_init(&dc, 0, 0);
+       br_x509_decoder_push(&dc, xc->data, xc->data_len);
+       err = br_x509_decoder_last_error(&dc);
+       if (err != 0) {
+               fprintf(stderr,
+                       "ERROR: certificate decoding failed with error %d\n",
+                       -err);
+               return 0;
+       }
+       return br_x509_decoder_get_signer_key_type(&dc);
+}
+
 static void
 static void
-xwc_start_chain(const br_x509_class **ctx,
-       unsigned expected_key_type, const char *server_name)
+xwc_start_chain(const br_x509_class **ctx, const char *server_name)
 {
        x509_noanchor_context *xwc;
 
        xwc = (x509_noanchor_context *)ctx;
 {
        x509_noanchor_context *xwc;
 
        xwc = (x509_noanchor_context *)ctx;
-       (*xwc->inner)->start_chain(xwc->inner,
-               expected_key_type, server_name);
+       (*xwc->inner)->start_chain(xwc->inner, server_name);
 }
 
 static void
 }
 
 static void
@@ -190,12 +207,12 @@ xwc_end_chain(const br_x509_class **ctx)
 }
 
 static const br_x509_pkey *
 }
 
 static const br_x509_pkey *
-xwc_get_pkey(const br_x509_class *const *ctx)
+xwc_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
 {
        x509_noanchor_context *xwc;
 
        xwc = (x509_noanchor_context *)ctx;
 {
        x509_noanchor_context *xwc;
 
        xwc = (x509_noanchor_context *)ctx;
-       return (*xwc->inner)->get_pkey(xwc->inner);
+       return (*xwc->inner)->get_pkey(xwc->inner, usages);
 }
 
 /* see brssl.h */
 }
 
 /* see brssl.h */
index 72bdbd1..102d43b 100644 (file)
@@ -117,6 +117,308 @@ host_connect(const char *host, const char *port, int verbose)
        return fd;
 }
 
        return fd;
 }
 
+typedef struct {
+       const br_ssl_client_certificate_class *vtable;
+       int verbose;
+       br_x509_certificate *chain;
+       size_t chain_len;
+       private_key *sk;
+       int issuer_key_type;
+} ccert_context;
+
+static void
+cc_start_name_list(const br_ssl_client_certificate_class **pctx)
+{
+       ccert_context *zc;
+
+       zc = (ccert_context *)pctx;
+       if (zc->verbose) {
+               fprintf(stderr, "Server requests a client certificate.\n");
+               fprintf(stderr, "--- anchor DN list start ---\n");
+       }
+}
+
+static void
+cc_start_name(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+       ccert_context *zc;
+
+       zc = (ccert_context *)pctx;
+       if (zc->verbose) {
+               fprintf(stderr, "new anchor name, length = %u\n",
+                       (unsigned)len);
+       }
+}
+
+static void
+cc_append_name(const br_ssl_client_certificate_class **pctx,
+       const unsigned char *data, size_t len)
+{
+       ccert_context *zc;
+
+       zc = (ccert_context *)pctx;
+       if (zc->verbose) {
+               size_t u;
+
+               for (u = 0; u < len; u ++) {
+                       if (u == 0) {
+                               fprintf(stderr, "  ");
+                       } else if (u > 0 && u % 16 == 0) {
+                               fprintf(stderr, "\n  ");
+                       }
+                       fprintf(stderr, " %02x", data[u]);
+               }
+               if (len > 0) {
+                       fprintf(stderr, "\n");
+               }
+       }
+}
+
+static void
+cc_end_name(const br_ssl_client_certificate_class **pctx)
+{
+       (void)pctx;
+}
+
+static void
+cc_end_name_list(const br_ssl_client_certificate_class **pctx)
+{
+       ccert_context *zc;
+
+       zc = (ccert_context *)pctx;
+       if (zc->verbose) {
+               fprintf(stderr, "--- anchor DN list end ---\n");
+       }
+}
+
+static void
+print_hashes(unsigned hh, unsigned hh2)
+{
+       int i;
+
+       for (i = 0; i < 8; i ++) {
+               const char *name;
+
+               name = hash_function_name(i);
+               if (((hh >> i) & 1) != 0) {
+                       fprintf(stderr, " %s", name);
+               } else if (((hh2 >> i) & 1) != 0) {
+                       fprintf(stderr, " (%s)", name);
+               }
+       }
+}
+
+static int
+choose_hash(unsigned hh)
+{
+       static const int f[] = {
+               br_sha256_ID, br_sha224_ID, br_sha384_ID, br_sha512_ID,
+               br_sha1_ID, br_md5sha1_ID, -1
+       };
+
+       size_t u;
+
+       for (u = 0; f[u] >= 0; u ++) {
+               if (((hh >> f[u]) & 1) != 0) {
+                       return f[u];
+               }
+       }
+       return -1;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+       const br_ssl_client_context *cc, uint32_t auth_types,
+       br_ssl_client_certificate *choices)
+{
+       ccert_context *zc;
+       int scurve;
+
+       zc = (ccert_context *)pctx;
+       scurve = br_ssl_client_get_server_curve(cc);
+       if (zc->verbose) {
+               unsigned hashes;
+
+               hashes = br_ssl_client_get_server_hashes(cc);
+               if ((auth_types & 0x00FF) != 0) {
+                       fprintf(stderr, "supported: RSA signatures:");
+                       print_hashes(auth_types, hashes);
+                       fprintf(stderr, "\n");
+               }
+               if ((auth_types & 0xFF00) != 0) {
+                       fprintf(stderr, "supported: ECDSA signatures:");
+                       print_hashes(auth_types >> 8, hashes >> 8);
+                       fprintf(stderr, "\n");
+               }
+               if ((auth_types & 0x010000) != 0) {
+                       fprintf(stderr, "supported:"
+                               " fixed ECDH (cert signed with RSA)\n");
+               }
+               if ((auth_types & 0x020000) != 0) {
+                       fprintf(stderr, "supported:"
+                               " fixed ECDH (cert signed with ECDSA)\n");
+               }
+               if (scurve) {
+                       fprintf(stderr, "server key curve: %s (%d)\n",
+                               ec_curve_name(scurve), scurve);
+               } else {
+                       fprintf(stderr, "server key is not EC\n");
+               }
+       }
+       switch (zc->sk->key_type) {
+       case BR_KEYTYPE_RSA:
+               if ((choices->hash_id = choose_hash(auth_types)) >= 0) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "using RSA, hash = %d (%s)\n",
+                                       choices->hash_id,
+                                       hash_function_name(choices->hash_id));
+                       }
+                       choices->auth_type = BR_AUTH_RSA;
+                       choices->chain = zc->chain;
+                       choices->chain_len = zc->chain_len;
+                       return;
+               }
+               break;
+       case BR_KEYTYPE_EC:
+               if (zc->issuer_key_type != 0
+                       && scurve == zc->sk->key.ec.curve)
+               {
+                       int x;
+
+                       x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17;
+                       if (((auth_types >> x) & 1) != 0) {
+                               if (zc->verbose) {
+                                       fprintf(stderr, "using static ECDH\n");
+                               }
+                               choices->auth_type = BR_AUTH_ECDH;
+                               choices->hash_id = -1;
+                               choices->chain = zc->chain;
+                               choices->chain_len = zc->chain_len;
+                               return;
+                       }
+               }
+               if ((choices->hash_id = choose_hash(auth_types >> 8)) >= 0) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "using ECDSA, hash = %d (%s)\n",
+                                       choices->hash_id,
+                                       hash_function_name(choices->hash_id));
+                       }
+                       choices->auth_type = BR_AUTH_ECDSA;
+                       choices->chain = zc->chain;
+                       choices->chain_len = zc->chain_len;
+                       return;
+               }
+               break;
+       }
+       if (zc->verbose) {
+               fprintf(stderr, "no matching client certificate\n");
+       }
+       choices->chain = NULL;
+       choices->chain_len = 0;
+}
+
+static uint32_t
+cc_do_keyx(const br_ssl_client_certificate_class **pctx,
+       unsigned char *data, size_t len)
+{
+       ccert_context *zc;
+
+       zc = (ccert_context *)pctx;
+       return br_ec_prime_i31.mul(data, len, zc->sk->key.ec.x,
+               zc->sk->key.ec.xlen, zc->sk->key.ec.curve);
+}
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+       int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+       ccert_context *zc;
+       unsigned char hv[64];
+
+       zc = (ccert_context *)pctx;
+       memcpy(hv, data, hv_len);
+       switch (zc->sk->key_type) {
+               const br_hash_class *hc;
+               const unsigned char *hash_oid;
+               uint32_t x;
+               size_t sig_len;
+
+       case BR_KEYTYPE_RSA:
+               hash_oid = get_hash_oid(hash_id);
+               if (hash_oid == NULL && hash_id != 0) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: cannot RSA-sign with"
+                                       " unknown hash function: %d\n",
+                                       hash_id);
+                       }
+                       return 0;
+               }
+               sig_len = (zc->sk->key.rsa.n_bitlen + 7) >> 3;
+               if (len < sig_len) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: cannot RSA-sign,"
+                                       " buffer is too small"
+                                       " (sig=%lu, buf=%lu)\n",
+                                       (unsigned long)sig_len,
+                                       (unsigned long)len);
+                       }
+                       return 0;
+               }
+               x = br_rsa_i31_pkcs1_sign(hash_oid, hv, hv_len,
+                       &zc->sk->key.rsa, data);
+               if (!x) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: RSA-sign failure\n");
+                       }
+                       return 0;
+               }
+               return sig_len;
+
+       case BR_KEYTYPE_EC:
+               hc = get_hash_impl(hash_id);
+               if (hc == NULL) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: cannot ECDSA-sign with"
+                                       " unknown hash function: %d\n",
+                                       hash_id);
+                       }
+                       return 0;
+               }
+               if (len < 139) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: cannot ECDSA-sign"
+                                       " (output buffer = %lu)\n",
+                                       (unsigned long)len);
+                       }
+                       return 0;
+               }
+               sig_len = br_ecdsa_i31_sign_asn1(&br_ec_prime_i31,
+                       hc, hv, &zc->sk->key.ec, data);
+               if (sig_len == 0) {
+                       if (zc->verbose) {
+                               fprintf(stderr, "ERROR: ECDSA-sign failure\n");
+                       }
+                       return 0;
+               }
+               return sig_len;
+
+       default:
+               return 0;
+       }
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+       sizeof(ccert_context),
+       cc_start_name_list,
+       cc_start_name,
+       cc_append_name,
+       cc_end_name,
+       cc_end_name_list,
+       cc_choose,
+       cc_do_keyx,
+       cc_do_sign
+};
+
 static void
 usage_client(void)
 {
 static void
 usage_client(void)
 {
@@ -139,6 +441,12 @@ usage_client(void)
        fprintf(stderr,
 "   -CA file        add certificates in 'file' to trust anchors\n");
        fprintf(stderr,
        fprintf(stderr,
 "   -CA file        add certificates in 'file' to trust anchors\n");
        fprintf(stderr,
+"   -cert file      set client certificate chain\n");
+       fprintf(stderr,
+"   -key file       set client private key (for certificate authentication)\n");
+       fprintf(stderr,
+"   -nostaticecdh   prohibit full-static ECDH (client certificate)\n");
+       fprintf(stderr,
 "   -list           list supported names (protocols, algorithms...)\n");
        fprintf(stderr,
 "   -vmin name      set minimum supported version (default: TLS-1.0)\n");
 "   -list           list supported names (protocols, algorithms...)\n");
        fprintf(stderr,
 "   -vmin name      set minimum supported version (default: TLS-1.0)\n");
@@ -179,6 +487,11 @@ do_client(int argc, char *argv[])
        br_x509_minimal_context xc;
        x509_noanchor_context xwc;
        const br_hash_class *dnhash;
        br_x509_minimal_context xc;
        x509_noanchor_context xwc;
        const br_hash_class *dnhash;
+       ccert_context zc;
+       br_x509_certificate *chain;
+       size_t chain_len;
+       private_key *sk;
+       int nostaticecdh;
        unsigned char *iobuf;
        size_t iobuf_len;
        size_t minhello_len;
        unsigned char *iobuf;
        size_t iobuf_len;
        size_t minhello_len;
@@ -200,6 +513,10 @@ do_client(int argc, char *argv[])
        num_suites = 0;
        hfuns = 0;
        suite_ids = NULL;
        num_suites = 0;
        hfuns = 0;
        suite_ids = NULL;
+       chain = NULL;
+       chain_len = 0;
+       sk = NULL;
+       nostaticecdh = 0;
        iobuf = NULL;
        iobuf_len = 0;
        minhello_len = (size_t)-1;
        iobuf = NULL;
        iobuf_len = 0;
        minhello_len = (size_t)-1;
@@ -279,6 +596,44 @@ do_client(int argc, char *argv[])
                                usage_client();
                                goto client_exit_error;
                        }
                                usage_client();
                                goto client_exit_error;
                        }
+               } else if (eqstr(arg, "-cert")) {
+                       if (++ i >= argc) {
+                               fprintf(stderr,
+                                       "ERROR: no argument for '-cert'\n");
+                               usage_client();
+                               goto client_exit_error;
+                       }
+                       if (chain != NULL) {
+                               fprintf(stderr,
+                                       "ERROR: duplicate certificate chain\n");
+                               usage_client();
+                               goto client_exit_error;
+                       }
+                       arg = argv[i];
+                       chain = read_certificates(arg, &chain_len);
+                       if (chain == NULL || chain_len == 0) {
+                               goto client_exit_error;
+                       }
+               } else if (eqstr(arg, "-key")) {
+                       if (++ i >= argc) {
+                               fprintf(stderr,
+                                       "ERROR: no argument for '-key'\n");
+                               usage_client();
+                               goto client_exit_error;
+                       }
+                       if (sk != NULL) {
+                               fprintf(stderr,
+                                       "ERROR: duplicate private key\n");
+                               usage_client();
+                               goto client_exit_error;
+                       }
+                       arg = argv[i];
+                       sk = read_private_key(arg);
+                       if (sk == NULL) {
+                               goto client_exit_error;
+                       }
+               } else if (eqstr(arg, "-nostaticecdh")) {
+                       nostaticecdh = 1;
                } else if (eqstr(arg, "-list")) {
                        list_names();
                        goto client_exit;
                } else if (eqstr(arg, "-list")) {
                        list_names();
                        goto client_exit;
@@ -412,7 +767,7 @@ do_client(int argc, char *argv[])
        }
        if (u == 0) {
                host = xstrdup(server_name);
        }
        if (u == 0) {
                host = xstrdup(server_name);
-               port = "443";
+               port = xstrdup("443");
        } else {
                port = xstrdup(server_name + u);
                host = xmalloc(u);
        } else {
                port = xstrdup(server_name + u);
                host = xmalloc(u);
@@ -423,6 +778,19 @@ do_client(int argc, char *argv[])
                sni = host;
        }
 
                sni = host;
        }
 
+       if (chain == NULL && sk != NULL) {
+               fprintf(stderr, "ERROR: private key specified, but"
+                       " no certificate chain\n");
+               usage_client();
+               goto client_exit_error;
+       }
+       if (chain != NULL && sk == NULL) {
+               fprintf(stderr, "ERROR: certificate chain specified, but"
+                       " no private key\n");
+               usage_client();
+               goto client_exit_error;
+       }
+
        if (vmin == 0) {
                vmin = BR_TLS10;
        }
        if (vmin == 0) {
                vmin = BR_TLS10;
        }
@@ -560,11 +928,13 @@ do_client(int argc, char *argv[])
                }
                if ((req & REQ_ECDHE_RSA) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
                }
                if ((req & REQ_ECDHE_RSA) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
-                       br_ssl_client_set_rsavrfy(&cc, &br_rsa_i31_pkcs1_vrfy);
+                       br_ssl_engine_set_rsavrfy(&cc.eng,
+                               &br_rsa_i31_pkcs1_vrfy);
                }
                if ((req & REQ_ECDHE_ECDSA) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
                }
                if ((req & REQ_ECDHE_ECDSA) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
-                       br_ssl_client_set_ecdsa(&cc, &br_ecdsa_i31_vrfy_asn1);
+                       br_ssl_engine_set_ecdsa(&cc.eng,
+                               &br_ecdsa_i31_vrfy_asn1);
                }
                if ((req & REQ_ECDH) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
                }
                if ((req & REQ_ECDH) != 0) {
                        br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
@@ -624,6 +994,23 @@ do_client(int argc, char *argv[])
        }
        br_ssl_engine_set_all_flags(&cc.eng, flags);
 
        }
        br_ssl_engine_set_all_flags(&cc.eng, flags);
 
+       if (chain != NULL) {
+               zc.vtable = &ccert_vtable;
+               zc.verbose = verbose;
+               zc.chain = chain;
+               zc.chain_len = chain_len;
+               zc.sk = sk;
+               if (nostaticecdh || sk->key_type != BR_KEYTYPE_EC) {
+                       zc.issuer_key_type = 0;
+               } else {
+                       zc.issuer_key_type = get_cert_signer_algo(&chain[0]);
+                       if (zc.issuer_key_type == 0) {
+                               goto client_exit_error;
+                       }
+               }
+               br_ssl_client_set_client_certificate(&cc, &zc.vtable);
+       }
+
        br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
        br_ssl_client_reset(&cc, sni, 0);
 
        br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
        br_ssl_client_reset(&cc, sni, 0);
 
@@ -657,9 +1044,12 @@ do_client(int argc, char *argv[])
         */
 client_exit:
        xfree(host);
         */
 client_exit:
        xfree(host);
+       xfree(port);
        xfree(suites);
        xfree(suite_ids);
        VEC_CLEAREXT(anchors, &free_ta_contents);
        xfree(suites);
        xfree(suite_ids);
        VEC_CLEAREXT(anchors, &free_ta_contents);
+       free_certificates(chain, chain_len);
+       free_private_key(sk);
        xfree(iobuf);
        if (fd >= 0) {
                close(fd);
        xfree(iobuf);
        if (fd >= 0) {
                close(fd);
index e9c6dfa..22f0c30 100644 (file)
@@ -157,7 +157,18 @@ static struct {
        }, {
                BR_ERR_BAD_SIGNATURE,
                "BR_ERR_BAD_SIGNATURE",
        }, {
                BR_ERR_BAD_SIGNATURE,
                "BR_ERR_BAD_SIGNATURE",
-               "Invalid signature on ServerKeyExchange message."
+               "Invalid signature in ServerKeyExchange or"
+               " CertificateVerify message."
+       }, {
+               BR_ERR_WRONG_KEY_USAGE,
+               "BR_ERR_WRONG_KEY_USAGE",
+               "Peer's public key does not have the proper type or is"
+               " not allowed for the requested operation."
+       }, {
+               BR_ERR_NO_CLIENT_AUTH,
+               "BR_ERR_NO_CLIENT_AUTH",
+               "Client did not send a certificate upon request, or the"
+               " client certificate could not be validated."
        }, {
                BR_ERR_IO,
                "BR_ERR_IO",
        }, {
                BR_ERR_IO,
                "BR_ERR_IO",
index 21c8166..651d51a 100644 (file)
@@ -300,3 +300,15 @@ read_certificates(const char *fname, size_t *num)
        VEC_CLEAR(cert_list);
        return xcs;
 }
        VEC_CLEAR(cert_list);
        return xcs;
 }
+
+/* see brssl.h */
+void
+free_certificates(br_x509_certificate *certs, size_t num)
+{
+       size_t u;
+
+       for (u = 0; u < num; u ++) {
+               xfree(certs[u].data);
+       }
+       xfree(certs);
+}
index 278a3b2..f7394be 100644 (file)
@@ -168,3 +168,64 @@ free_private_key(private_key *sk)
        }
        xfree(sk);
 }
        }
        xfree(sk);
 }
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+       HASH_OID_SHA1,
+       HASH_OID_SHA224,
+       HASH_OID_SHA256,
+       HASH_OID_SHA384,
+       HASH_OID_SHA512
+};
+
+/* see brssl.h */
+const unsigned char *
+get_hash_oid(int id)
+{
+       if (id >= 2 && id <= 6) {
+               return HASH_OID[id - 2];
+       } else {
+               return NULL;
+       }
+}
+
+/* see brssl.h */
+const br_hash_class *
+get_hash_impl(int hash_id)
+{
+       size_t u;
+
+       for (u = 0; hash_functions[u].name; u ++) {
+               const br_hash_class *hc;
+               int id;
+
+               hc = hash_functions[u].hclass;
+               id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+               if (id == hash_id) {
+                       return hc;
+               }
+       }
+       return NULL;
+}
index 191dfeb..06b2cdb 100644 (file)
@@ -651,3 +651,20 @@ ec_curve_name(int curve)
                return "unknown";
        }
 }
                return "unknown";
        }
 }
+
+/* see brssl.h */
+const char *
+hash_function_name(int id)
+{
+       switch (id) {
+       case br_md5sha1_ID:  return "MD5+SHA-1";
+       case br_md5_ID:      return "MD5";
+       case br_sha1_ID:     return "SHA-1";
+       case br_sha224_ID:   return "SHA-224";
+       case br_sha256_ID:   return "SHA-256";
+       case br_sha384_ID:   return "SHA-384";
+       case br_sha512_ID:   return "SHA-512";
+       default:
+               return "unknown";
+       }
+}
index b81ce07..5e9315d 100644 (file)
@@ -214,6 +214,10 @@ usage_server(void)
        fprintf(stderr,
 "   -key fname      read private key from file 'fname'\n");
        fprintf(stderr,
        fprintf(stderr,
 "   -key fname      read private key from file 'fname'\n");
        fprintf(stderr,
+"   -CA file        add trust anchors from 'file' (for client auth)\n");
+       fprintf(stderr,
+"   -anon_ok        request but do not require a client certificate\n");
+       fprintf(stderr,
 "   -list           list supported names (protocols, algorithms...)\n");
        fprintf(stderr,
 "   -vmin name      set minimum supported version (default: TLS-1.0)\n");
 "   -list           list supported names (protocols, algorithms...)\n");
        fprintf(stderr,
 "   -vmin name      set minimum supported version (default: TLS-1.0)\n");
@@ -237,20 +241,43 @@ typedef struct {
        private_key *sk;
 } policy_context;
 
        private_key *sk;
 } policy_context;
 
+static void
+print_hashes(unsigned chashes)
+{
+       int i;
+
+       for (i = 2; i <= 6; i ++) {
+               if ((chashes >> i) & 1) {
+                       int z;
+
+                       switch (i) {
+                       case 3: z = 224; break;
+                       case 4: z = 256; break;
+                       case 5: z = 384; break;
+                       case 6: z = 512; break;
+                       default:
+                               z = 1;
+                               break;
+                       }
+                       fprintf(stderr, " sha%d", z);
+               }
+       }
+}
+
 static int
 static int
-get_cert_signer_algo(br_x509_certificate *xc)
+choose_hash(unsigned chashes)
 {
 {
-       br_x509_decoder_context dc;
-       int err;
+       int hash_id;
 
 
-       br_x509_decoder_init(&dc, 0, 0);
-       br_x509_decoder_push(&dc, xc->data, xc->data_len);
-       err = br_x509_decoder_last_error(&dc);
-       if (err != 0) {
-               return -err;
-       } else {
-               return br_x509_decoder_get_signer_key_type(&dc);
+       for (hash_id = 6; hash_id >= 2; hash_id --) {
+               if (((chashes >> hash_id) & 1) != 0) {
+                       return hash_id;
+               }
        }
        }
+       /*
+        * Normally unreachable.
+        */
+       return 0;
 }
 
 static int
 }
 
 static int
@@ -262,16 +289,10 @@ sp_choose(const br_ssl_server_policy_class **pctx,
        const br_suite_translated *st;
        size_t u, st_num;
        unsigned chashes;
        const br_suite_translated *st;
        size_t u, st_num;
        unsigned chashes;
-       int hash_id;
 
        pc = (policy_context *)pctx;
        st = br_ssl_server_get_client_suites(cc, &st_num);
        chashes = br_ssl_server_get_client_hashes(cc);
 
        pc = (policy_context *)pctx;
        st = br_ssl_server_get_client_suites(cc, &st_num);
        chashes = br_ssl_server_get_client_hashes(cc);
-       for (hash_id = 6; hash_id >= 2; hash_id --) {
-               if ((chashes >> hash_id) & 1) {
-                       break;
-               }
-       }
        if (pc->verbose) {
                fprintf(stderr, "Client parameters:\n");
                fprintf(stderr, "   Maximum version:      ");
        if (pc->verbose) {
                fprintf(stderr, "Client parameters:\n");
                fprintf(stderr, "   Maximum version:      ");
@@ -301,24 +322,17 @@ sp_choose(const br_ssl_server_policy_class **pctx,
                        get_suite_name_ext(st[u][0], csn, sizeof csn);
                        fprintf(stderr, "      %s\n", csn);
                }
                        get_suite_name_ext(st[u][0], csn, sizeof csn);
                        fprintf(stderr, "      %s\n", csn);
                }
-               fprintf(stderr, "   Common hash functions:");
-               for (u = 2; u <= 6; u ++) {
-                       if ((chashes >> u) & 1) {
-                               int z;
-
-                               switch (u) {
-                               case 3: z = 224; break;
-                               case 4: z = 256; break;
-                               case 5: z = 384; break;
-                               case 6: z = 512; break;
-                               default:
-                                       z = 1;
-                                       break;
-                               }
-                               fprintf(stderr, " sha%d", z);
-                       }
+               fprintf(stderr, "   Common sign+hash functions:\n");
+               if ((chashes & 0xFF) != 0) {
+                       fprintf(stderr, "      with RSA:");
+                       print_hashes(chashes);
+                       fprintf(stderr, "\n");
+               }
+               if ((chashes >> 8) != 0) {
+                       fprintf(stderr, "      with ECDSA:");
+                       print_hashes(chashes >> 8);
+                       fprintf(stderr, "\n");
                }
                }
-               fprintf(stderr, "\n");
        }
        for (u = 0; u < st_num; u ++) {
                unsigned tt;
        }
        for (u = 0; u < st_num; u ++) {
                unsigned tt;
@@ -337,9 +351,10 @@ sp_choose(const br_ssl_server_policy_class **pctx,
                                if (br_ssl_engine_get_version(&cc->eng)
                                        < BR_TLS12)
                                {
                                if (br_ssl_engine_get_version(&cc->eng)
                                        < BR_TLS12)
                                {
-                                       hash_id = 0;
+                                       choices->hash_id = 0;
+                               } else {
+                                       choices->hash_id = choose_hash(chashes);
                                }
                                }
-                               choices->hash_id = hash_id;
                                goto choose_ok;
                        }
                        break;
                                goto choose_ok;
                        }
                        break;
@@ -349,9 +364,11 @@ sp_choose(const br_ssl_server_policy_class **pctx,
                                if (br_ssl_engine_get_version(&cc->eng)
                                        < BR_TLS12)
                                {
                                if (br_ssl_engine_get_version(&cc->eng)
                                        < BR_TLS12)
                                {
-                                       hash_id = br_sha1_ID;
+                                       choices->hash_id = br_sha1_ID;
+                               } else {
+                                       choices->hash_id =
+                                               choose_hash(chashes >> 8);
                                }
                                }
-                               choices->hash_id = hash_id;
                                goto choose_ok;
                        }
                        break;
                                goto choose_ok;
                        }
                        break;
@@ -409,55 +426,6 @@ sp_do_keyx(const br_ssl_server_policy_class **pctx,
        }
 }
 
        }
 }
 
-/*
- * OID for hash functions in RSA signatures.
- */
-static const unsigned char HASH_OID_SHA1[] = {
-       0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
-};
-
-static const unsigned char HASH_OID_SHA224[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
-};
-
-static const unsigned char HASH_OID_SHA256[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
-};
-
-static const unsigned char HASH_OID_SHA384[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
-};
-
-static const unsigned char HASH_OID_SHA512[] = {
-       0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
-};
-
-static const unsigned char *HASH_OID[] = {
-       HASH_OID_SHA1,
-       HASH_OID_SHA224,
-       HASH_OID_SHA256,
-       HASH_OID_SHA384,
-       HASH_OID_SHA512
-};
-
-static const br_hash_class *
-get_hash_impl(int hash_id)
-{
-       size_t u;
-
-       for (u = 0; hash_functions[u].name; u ++) {
-               const br_hash_class *hc;
-               int id;
-
-               hc = hash_functions[u].hclass;
-               id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
-               if (id == hash_id) {
-                       return hc;
-               }
-       }
-       return NULL;
-}
-
 static size_t
 sp_do_sign(const br_ssl_server_policy_class **pctx,
        int hash_id, size_t hv_len, unsigned char *data, size_t len)
 static size_t
 sp_do_sign(const br_ssl_server_policy_class **pctx,
        int hash_id, size_t hv_len, unsigned char *data, size_t len)
@@ -474,11 +442,8 @@ sp_do_sign(const br_ssl_server_policy_class **pctx,
                const br_hash_class *hc;
 
        case BR_KEYTYPE_RSA:
                const br_hash_class *hc;
 
        case BR_KEYTYPE_RSA:
-               if (hash_id == 0) {
-                       hash_oid = NULL;
-               } else if (hash_id >= 2 && hash_id <= 6) {
-                       hash_oid = HASH_OID[hash_id - 2];
-               } else {
+               hash_oid = get_hash_oid(hash_id);
+               if (hash_oid == NULL && hash_id != 0) {
                        if (pc->verbose) {
                                fprintf(stderr, "ERROR: cannot RSA-sign with"
                                        " unknown hash function: %d\n",
                        if (pc->verbose) {
                                fprintf(stderr, "ERROR: cannot RSA-sign with"
                                        " unknown hash function: %d\n",
@@ -566,6 +531,9 @@ do_server(int argc, char *argv[])
        size_t chain_len;
        int cert_signer_algo;
        private_key *sk;
        size_t chain_len;
        int cert_signer_algo;
        private_key *sk;
+       anchor_list anchors = VEC_INIT;
+       br_x509_minimal_context xc;
+       const br_hash_class *dnhash;
        size_t u;
        br_ssl_server_context cc;
        policy_context pc;
        size_t u;
        br_ssl_server_context cc;
        policy_context pc;
@@ -713,6 +681,20 @@ do_server(int argc, char *argv[])
                        if (sk == NULL) {
                                goto server_exit_error;
                        }
                        if (sk == NULL) {
                                goto server_exit_error;
                        }
+               } else if (eqstr(arg, "-CA")) {
+                       if (++ i >= argc) {
+                               fprintf(stderr,
+                                       "ERROR: no argument for '-CA'\n");
+                               usage_server();
+                               goto server_exit_error;
+                       }
+                       arg = argv[i];
+                       if (read_trust_anchors(&anchors, arg) == 0) {
+                               usage_server();
+                               goto server_exit_error;
+                       }
+               } else if (eqstr(arg, "-anon_ok")) {
+                       flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH;
                } else if (eqstr(arg, "-list")) {
                        list_names();
                        goto server_exit;
                } else if (eqstr(arg, "-list")) {
                        list_names();
                        goto server_exit;
@@ -872,11 +854,10 @@ do_server(int argc, char *argv[])
                break;
        }
        cert_signer_algo = get_cert_signer_algo(chain);
                break;
        }
        cert_signer_algo = get_cert_signer_algo(chain);
-       if (cert_signer_algo < 0) {
-               fprintf(stderr, "ERROR: server certificate cannot be"
-                       " decoded (err=%d)\n", -cert_signer_algo);
+       if (cert_signer_algo == 0) {
                goto server_exit_error;
                goto server_exit_error;
-       } else if (verbose) {
+       }
+       if (verbose) {
                const char *csas;
 
                switch (cert_signer_algo) {
                const char *csas;
 
                switch (cert_signer_algo) {
@@ -980,6 +961,7 @@ do_server(int argc, char *argv[])
        }
        br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
 
        }
        br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
 
+       dnhash = NULL;
        for (u = 0; hash_functions[u].name; u ++) {
                const br_hash_class *hc;
                int id;
        for (u = 0; hash_functions[u].name; u ++) {
                const br_hash_class *hc;
                int id;
@@ -987,6 +969,7 @@ do_server(int argc, char *argv[])
                hc = hash_functions[u].hclass;
                id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
                if ((hfuns & ((unsigned)1 << id)) != 0) {
                hc = hash_functions[u].hclass;
                id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
                if ((hfuns & ((unsigned)1 << id)) != 0) {
+                       dnhash = hc;
                        br_ssl_engine_set_hash(&cc.eng, id, hc);
                }
        }
                        br_ssl_engine_set_hash(&cc.eng, id, hc);
                }
        }
@@ -1007,6 +990,11 @@ do_server(int argc, char *argv[])
        br_ssl_session_cache_lru_init(&lru, cache, cache_len);
        br_ssl_server_set_cache(&cc, &lru.vtable);
 
        br_ssl_session_cache_lru_init(&lru, cache, cache_len);
        br_ssl_server_set_cache(&cc, &lru.vtable);
 
+       /*
+        * Set the policy handler (that chooses the actual cipher suite,
+        * selects the certificate chain, and runs the private key
+        * operations).
+        */
        pc.vtable = &policy_vtable;
        pc.verbose = verbose;
        pc.chain = chain;
        pc.vtable = &policy_vtable;
        pc.verbose = verbose;
        pc.chain = chain;
@@ -1015,6 +1003,36 @@ do_server(int argc, char *argv[])
        pc.sk = sk;
        br_ssl_server_set_policy(&cc, &pc.vtable);
 
        pc.sk = sk;
        br_ssl_server_set_policy(&cc, &pc.vtable);
 
+       /*
+        * If trust anchors have been configured, then set an X.509
+        * validation engine and activate client certificate
+        * authentication.
+        */
+       if (VEC_LEN(anchors) != 0) {
+               br_x509_minimal_init(&xc, dnhash,
+                       &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+               for (u = 0; hash_functions[u].name; u ++) {
+                       const br_hash_class *hc;
+                       int id;
+
+                       hc = hash_functions[u].hclass;
+                       id = (hc->desc >> BR_HASHDESC_ID_OFF)
+                               & BR_HASHDESC_ID_MASK;
+                       if ((hfuns & ((unsigned)1 << id)) != 0) {
+                               br_x509_minimal_set_hash(&xc, id, hc);
+                       }
+               }
+               br_ssl_engine_set_rsavrfy(&cc.eng, &br_rsa_i31_pkcs1_vrfy);
+               br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
+               br_ssl_engine_set_ecdsa(&cc.eng, &br_ecdsa_i31_vrfy_asn1);
+               br_x509_minimal_set_rsa(&xc, &br_rsa_i31_pkcs1_vrfy);
+               br_x509_minimal_set_ecdsa(&xc,
+                       &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
+               br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
+               br_ssl_server_set_trust_anchor_names_alt(&cc,
+                       &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+       }
+
        br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
 
        /*
        br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
 
        /*
@@ -1061,13 +1079,9 @@ do_server(int argc, char *argv[])
 server_exit:
        xfree(suites);
        xfree(suite_ids);
 server_exit:
        xfree(suites);
        xfree(suite_ids);
-       if (chain != NULL) {
-               for (u = 0; u < chain_len; u ++) {
-                       xfree(chain[u].data);
-               }
-               xfree(chain);
-       }
+       free_certificates(chain, chain_len);
        free_private_key(sk);
        free_private_key(sk);
+       VEC_CLEAREXT(anchors, &free_ta_contents);
        xfree(iobuf);
        xfree(cache);
        if (fd >= 0) {
        xfree(iobuf);
        xfree(cache);
        if (fd >= 0) {
index a29aae0..df72e2b 100644 (file)
@@ -93,7 +93,7 @@ print_ta_internals(br_x509_trust_anchor *ta, long ctr)
        char tmp[25];
 
        sprintf(tmp, "TA%ld_DN", ctr);
        char tmp[25];
 
        sprintf(tmp, "TA%ld_DN", ctr);
-       print_blob(tmp, ta->dn, ta->dn_len);
+       print_blob(tmp, ta->dn.data, ta->dn.len);
        switch (ta->pkey.key_type) {
        case BR_KEYTYPE_RSA:
                sprintf(tmp, "TA%ld_RSA_N", ctr);
        switch (ta->pkey.key_type) {
        case BR_KEYTYPE_RSA:
                sprintf(tmp, "TA%ld_RSA_N", ctr);
@@ -119,7 +119,8 @@ print_ta(br_x509_trust_anchor *ta, long ctr)
        char tmp[25];
 
        printf("\t{\n");
        char tmp[25];
 
        printf("\t{\n");
-       printf("\t\t(unsigned char *)TA%ld_DN, sizeof TA%ld_DN,\n", ctr, ctr);
+       printf("\t\t{ (unsigned char *)TA%ld_DN, sizeof TA%ld_DN },\n",
+               ctr, ctr);
        printf("\t\t%s,\n", (ta->flags & BR_X509_TA_CA)
                ? "BR_X509_TA_CA" : "0");
        printf("\t\t{\n");
        printf("\t\t%s,\n", (ta->flags & BR_X509_TA_CA)
                ? "BR_X509_TA_CA" : "0");
        printf("\t\t{\n");
index 064a61f..7405578 100644 (file)
@@ -181,9 +181,11 @@ do_verify(int argc, char *argv[])
        cert_list chain = VEC_INIT;
        size_t u;
        br_x509_minimal_context mc;
        cert_list chain = VEC_INIT;
        size_t u;
        br_x509_minimal_context mc;
-       int err_keyx, err_sign;
+       int err;
        int print_text, print_C;
        br_x509_pkey *pk;
        int print_text, print_C;
        br_x509_pkey *pk;
+       const br_x509_pkey *tpk;
+       unsigned usages;
 
        retcode = 0;
        verbose = 1;
 
        retcode = 0;
        verbose = 1;
@@ -191,8 +193,6 @@ do_verify(int argc, char *argv[])
        print_text = 0;
        print_C = 0;
        pk = NULL;
        print_text = 0;
        print_C = 0;
        pk = NULL;
-       err_keyx = 0;
-       err_sign = 0;
        for (i = 0; i < argc; i ++) {
                const char *arg;
 
        for (i = 0; i < argc; i ++) {
                const char *arg;
 
@@ -266,55 +266,44 @@ do_verify(int argc, char *argv[])
        br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
        br_x509_minimal_set_ecdsa(&mc,
                &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
        br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
        br_x509_minimal_set_ecdsa(&mc,
                &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
-       for (i = 0; i < 2; i ++) {
-               const br_x509_pkey *tpk;
-               int err;
 
 
-               mc.vtable->start_chain(&mc.vtable,
-                       i == 0 ? BR_KEYTYPE_KEYX : BR_KEYTYPE_SIGN, sni);
-               for (u = 0; u < VEC_LEN(chain); u ++) {
-                       br_x509_certificate *xc;
+       mc.vtable->start_chain(&mc.vtable, sni);
+       for (u = 0; u < VEC_LEN(chain); u ++) {
+               br_x509_certificate *xc;
 
 
-                       xc = &VEC_ELT(chain, u);
-                       mc.vtable->start_cert(&mc.vtable, xc->data_len);
-                       mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
-                       mc.vtable->end_cert(&mc.vtable);
-               }
-               err = mc.vtable->end_chain(&mc.vtable);
-               if (i == 0) {
-                       err_keyx = err;
-               } else {
-                       err_sign = err;
-               }
-               tpk = mc.vtable->get_pkey(&mc.vtable);
-               if (pk == NULL && tpk != NULL) {
-                       pk = xpkeydup(tpk);
-               }
+               xc = &VEC_ELT(chain, u);
+               mc.vtable->start_cert(&mc.vtable, xc->data_len);
+               mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
+               mc.vtable->end_cert(&mc.vtable);
+       }
+       err = mc.vtable->end_chain(&mc.vtable);
+       tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
+       if (tpk != NULL) {
+               pk = xpkeydup(tpk);
        }
        }
-       if (err_keyx == 0 || err_sign == 0) {
+
+       if (err == 0) {
                if (verbose) {
                if (verbose) {
-                       fprintf(stderr, "Validation success");
-                       if (err_keyx == 0 && err_sign == 0) {
-                               fprintf(stderr, " (key exchange, sign)\n");
-                       } else if (err_keyx == 0) {
-                               fprintf(stderr, " (key exchange)\n");
-                       } else if (err_sign == 0) {
-                               fprintf(stderr, " (signature)\n");
+                       int hkx;
+
+                       fprintf(stderr, "Validation success; usages:");
+                       hkx = 0;
+                       if (usages & BR_KEYTYPE_KEYX) {
+                               fprintf(stderr, " key exchange");
+                               hkx = 1;
                        }
                        }
+                       if (usages & BR_KEYTYPE_SIGN) {
+                               if (hkx) {
+                                       fprintf(stderr, ",");
+                               }
+                               fprintf(stderr, " signature");
+                       }
+                       fprintf(stderr, "\n");
                }
        } else {
                if (verbose) {
                }
        } else {
                if (verbose) {
-                       int err;
                        const char *errname, *errmsg;
 
                        const char *errname, *errmsg;
 
-                       /*
-                        * If the two error codes differ, we want the one
-                        * which is not a "forbidden key usage".
-                        */
-                       err = err_keyx;
-                       if (err == BR_ERR_X509_FORBIDDEN_KEY_USAGE) {
-                               err = err_sign;
-                       }
                        fprintf(stderr, "Validation failed, err = %d", err);
                        errname = find_error_name(err, &errmsg);
                        if (errname != NULL) {
                        fprintf(stderr, "Validation failed, err = %d", err);
                        errname = find_error_name(err, &errmsg);
                        if (errname != NULL) {