Added support for client certificates (both client-side and server-side, but still missing an API for extracting the client identity from the certificate).

This commit is contained in:
Thomas Pornin 2016-12-10 17:35:06 +01:00
parent e9ce2f4e8c
commit e61ad42191
27 changed files with 4441 additions and 1482 deletions

View file

@ -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;
}

View file

@ -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;
}

View 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_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_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);

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,7 @@ make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
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.
@ -145,9 +145,11 @@ static const unsigned char *HASH_OID[] = {
/*
* 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
*
* 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;
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);
@ -198,14 +200,14 @@ verify_SKE_sig(br_ssl_client_context *ctx,
} 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 {
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;
@ -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.
*
@ -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;
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;
@ -292,6 +294,73 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
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
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
@ -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 ;
\ 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
@ -709,80 +771,26 @@ cc: DEBUG-BLOB ( addr len -- ) {
resume
;
cc: x509-start-chain ( expected-key-type -- ) {
cc: set-server-curve ( -- ) {
const br_x509_class *xc;
const br_x509_pkey *pk;
xc = *(ENG->x509ctx);
xc->start_chain(ENG->x509ctx, T0_POP(), ENG->server_name);
pk = xc->get_pkey(ENG->x509ctx, NULL);
CTX->server_curve =
(pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0;
}
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));
}
\ 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
x509-start-chain
-1 read-Certificate
dup 0< if neg fail then
dup ifnot ERR_UNEXPECTED fail then
over and <> if ERR_WRONG_KEY_USAGE fail then
\ 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 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)
@ -851,15 +859,166 @@ cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) {
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 -- )
\ 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-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;
@ -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
@ -903,6 +1082,20 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
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.
@ -924,7 +1117,9 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
\ 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.
@ -956,12 +1151,27 @@ cc: do-ecdh ( echde prf_id -- ulen ) {
more-incoming-bytes? if ERR_UNEXPECTED fail then
seen-CR if
\ TODO: client certificate support.
write-empty-Certificate
then
write-ClientKeyExchange
\ If the server requested a client certificate, then
\ we must write a Certificate message (it may be
\ empty).
write-Certificate
\ TODO: CertificateVerify
\ 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
-1 write-CCS-Finished
-1 read-CCS-Finished

View file

@ -145,12 +145,8 @@ addr-eng: version_max
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: session_id_len
\ addr-eng: session_id
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_SIGNATURE
err: ERR_WRONG_KEY_USAGE
err: ERR_NO_CLIENT_AUTH
\ 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).
\ Note: this (on purpose) skips MD5.
cc: supported-hash-functions ( -- x num ) {
int i;
unsigned x, num;
@ -236,6 +236,16 @@ cc: supported-hash-functions ( -- x 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);
@ -1020,3 +1030,186 @@ cc: compute-Finished-inner ( from_client prf_id -- ) {
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 ;

File diff suppressed because it is too large Load diff

View file

@ -140,6 +140,35 @@ do_ecdh(br_ssl_server_context *ctx, int prf_id,
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
@ -258,6 +287,94 @@ do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
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
\ 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 ;
@ -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->chain = choices.chain;
CTX->chain_len = choices.chain_len;
ENG->chain = choices.chain;
ENG->chain_len = choices.chain_len;
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.
\ 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
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
@ -684,6 +785,11 @@ cc: save-session ( -- ) {
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
@ -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
\ (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
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
@ -791,63 +897,6 @@ cc: save-session ( -- ) {
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 ) {
@ -900,6 +949,166 @@ cc: do-ecdhe-part1 ( curve -- len ) {
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 ;
@ -927,11 +1136,18 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
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.
@ -951,6 +1167,116 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
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
@ -974,11 +1300,54 @@ cc: do-ecdhe-part2 ( len prf_id -- ) {
else
\ Not a session resumption
write-ServerHello
write-Certificate
write-Certificate drop
write-ServerKeyExchange
ta-names-total-length if
write-CertificateRequest
then
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

View 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);
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;
}

View file

@ -27,29 +27,29 @@
/* 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->usages = usages;
}
/* 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->usages = usages;
}
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)expected_key_type;
(void)server_name;
}
@ -82,9 +82,15 @@ kk_end_chain(const br_x509_class **ctx)
}
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 */

View file

@ -239,8 +239,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,
}
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;
@ -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->expected_key_type = expected_key_type;
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 *
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;
@ -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 (usages != NULL) {
*usages = cc->key_usages;
}
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_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,
@ -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, 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(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, 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[] = {
@ -736,98 +736,97 @@ static const uint16_t t0_caddr[] = {
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,
1058,
1063,
1068,
1072,
1077,
1082,
1073,
1078,
1083,
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,
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; \
@ -848,7 +847,7 @@ name(void *ctx) \
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)
@ -1100,7 +1099,7 @@ br_x509_minimal_run(void *t0ctx)
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;
}
@ -1161,7 +1160,7 @@ br_x509_minimal_run(void *t0ctx)
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;
}
@ -1360,14 +1359,6 @@ br_x509_minimal_run(void *t0ctx)
}
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;
@ -1402,7 +1393,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 44: {
case 43: {
/* neg */
uint32_t a = T0_POP();
@ -1410,7 +1401,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 45: {
case 44: {
/* or */
uint32_t b = T0_POP();
@ -1419,12 +1410,12 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 46: {
case 45: {
/* over */
T0_PUSH(T0_PEEK(1));
}
break;
case 47: {
case 46: {
/* read-blob-inner */
uint32_t len = T0_POP();
@ -1450,7 +1441,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 48: {
case 47: {
/* read8-low */
if (CTX->hlen == 0) {
@ -1469,17 +1460,17 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 49: {
case 48: {
/* roll */
T0_ROLL(T0_POP());
}
break;
case 50: {
case 49: {
/* rot */
T0_ROT();
}
break;
case 51: {
case 50: {
/* set16 */
uint32_t addr = T0_POP();
@ -1487,7 +1478,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 52: {
case 51: {
/* set32 */
uint32_t addr = T0_POP();
@ -1495,7 +1486,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 53: {
case 52: {
/* set8 */
uint32_t addr = T0_POP();
@ -1503,7 +1494,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 54: {
case 53: {
/* start-dn-hash */
CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
@ -1511,7 +1502,7 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 55: {
case 54: {
/* start-tbs-hash */
br_multihash_init(&CTX->mhash);
@ -1519,19 +1510,19 @@ br_x509_minimal_run(void *t0ctx)
}
break;
case 56: {
case 55: {
/* stop-tbs-hash */
CTX->do_mhash = 0;
}
break;
case 57: {
case 56: {
/* swap */
T0_SWAP();
}
break;
case 58: {
case 57: {
/* zero-server-name */
T0_PUSHi(-(CTX->server_name == NULL));

View file

@ -188,8 +188,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx,
}
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;
@ -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->expected_key_type = expected_key_type;
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 *
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;
@ -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 (usages != NULL) {
*usages = cc->key_usages;
}
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));
}
addr: expected_key_type
addr: key_usages
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;
}
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;
}
@ -765,7 +766,7 @@ cc: check-trust-anchor-CA ( -- ) {
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;
}
@ -892,20 +893,14 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11
\ 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 )
\ 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
@ -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
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
@ -1070,15 +1078,8 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11
\ 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
@ -1286,6 +1287,9 @@ OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11
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