diff --git a/crypto/evp_extra/evp_asn1.c b/crypto/evp_extra/evp_asn1.c index 254222a673..c5e5ca5b81 100644 --- a/crypto/evp_extra/evp_asn1.c +++ b/crypto/evp_extra/evp_asn1.c @@ -71,19 +71,20 @@ #include "../fipsmodule/pqdsa/internal.h" // parse_key_type takes the algorithm cbs sequence |cbs| and extracts the OID. +// The extracted OID will be set on |out_oid| so that it may be used later in +// specific key type implementations like PQDSA. // The OID is then searched against ASN.1 methods for a method with that OID. // As the |OID| is read from |cbs| the buffer is advanced. // For the case of |NID_rsa| the method |rsa_asn1_meth| is returned. -// For the case of |EVP_PKEY_PQDSA| the method |pqdsa_asn1.meth| is returned, as -// the OID is not returned (and the |cbs| buffer is advanced) we return the OID -// as |cbs|. (This allows the specific OID, e.g. NID_MLDSA65 to be parsed by -// the type-specific decoding functions within the algorithm parameter.) -static const EVP_PKEY_ASN1_METHOD *parse_key_type(CBS *cbs) { +// For the case of |EVP_PKEY_PQDSA| the method |pqdsa_asn1.meth| is returned. +static const EVP_PKEY_ASN1_METHOD *parse_key_type(CBS *cbs, CBS *out_oid) { CBS oid; if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { return NULL; } + CBS_init(out_oid, CBS_data(&oid), CBS_len(&oid)); + const EVP_PKEY_ASN1_METHOD *const *asn1_methods = AWSLC_non_fips_pkey_evp_asn1_methods(); for (size_t i = 0; i < ASN1_EVP_PKEY_METHODS; i++) { @@ -103,18 +104,7 @@ static const EVP_PKEY_ASN1_METHOD *parse_key_type(CBS *cbs) { // The pkey_id for the pqdsa_asn1_meth is EVP_PKEY_PQDSA, as this holds all // asn1 functions for pqdsa types. However, the incoming CBS has the OID for // the specific algorithm. So we must search explicitly for the algorithm. - const EVP_PKEY_ASN1_METHOD * ret = PQDSA_find_asn1_by_nid(OBJ_cbs2nid(&oid)); - if (ret != NULL) { - // if |cbs| is empty after parsing |oid| from it, we overwrite the contents - // with |oid| so that we can call pub_decode/priv_decode with the |algorithm| - // populated as |oid|. - if (CBS_len(cbs) == 0) { - OPENSSL_memcpy(cbs, &oid, sizeof(oid)); - return ret; - } - } - - return NULL; + return PQDSA_find_asn1_by_nid(OBJ_cbs2nid(&oid)); } EVP_PKEY *EVP_parse_public_key(CBS *cbs) { @@ -129,7 +119,9 @@ EVP_PKEY *EVP_parse_public_key(CBS *cbs) { return NULL; } - const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); + CBS oid; + + const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm, &oid); if (method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; @@ -154,7 +146,7 @@ EVP_PKEY *EVP_parse_public_key(CBS *cbs) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); goto err; } - if (!ret->ameth->pub_decode(ret, &algorithm, &key)) { + if (!ret->ameth->pub_decode(ret, &oid, &algorithm, &key)) { goto err; } @@ -195,7 +187,9 @@ EVP_PKEY *EVP_parse_private_key(CBS *cbs) { return NULL; } - const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); + CBS oid; + + const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm, &oid); if (method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; @@ -236,7 +230,7 @@ EVP_PKEY *EVP_parse_private_key(CBS *cbs) { goto err; } - if (!ret->ameth->priv_decode(ret, &algorithm, &key, + if (!ret->ameth->priv_decode(ret, &oid, &algorithm, &key, has_pub ? &public_key : NULL)) { goto err; } diff --git a/crypto/evp_extra/evp_extra_test.cc b/crypto/evp_extra/evp_extra_test.cc index 6bd3460dc2..e8b53a618b 100644 --- a/crypto/evp_extra/evp_extra_test.cc +++ b/crypto/evp_extra/evp_extra_test.cc @@ -700,318 +700,345 @@ static const uint8_t kInvalidPrivateKey[] = { // kExampleMLDSA65KeyDER is a ML-DSA private key in ASN.1, DER format. // Of course, you should never use this key anywhere but in an example. static const uint8_t kExampleMLDSA65KeyDER[] = { -0x30, 0x82, 0xF, 0xD4, 0x2, 0x1, 0x0, 0x30, 0xB, 0x6, 0x9, 0x60, 0x86, -0x48, 0x1, 0x65, 0x3, 0x4, 0x3, 0x12, 0x4, 0x82, 0xF, 0xC0, 0x9B, 0x77, -0xAB, 0x96, 0x9D, 0x65, 0xA2, 0xC1, 0x55, 0x65, 0x2, 0x9B, 0xA5, 0xD4, 0xE5, -0x93, 0xA1, 0xAC, 0xE7, 0x3E, 0x8C, 0x61, 0xB7, 0xCB, 0xA1, 0x3E, 0x74, 0x8A, -0xC9, 0xC0, 0xA0, 0x63, 0x31, 0x99, 0xCE, 0x5B, 0x64, 0x5C, 0x4, 0xBC, 0xAA, -0x47, 0x73, 0x13, 0x4E, 0x53, 0x9F, 0x83, 0x81, 0x49, 0x98, 0x80, 0x58, 0xB2, -0xA1, 0xDB, 0xD8, 0xDB, 0xEB, 0xAD, 0x42, 0xD0, 0xFF, 0xEE, 0x18, 0x1A, 0x15, -0x58, 0x9C, 0x84, 0x7F, 0x2A, 0x73, 0x57, 0x63, 0x60, 0x82, 0xF7, 0xC6, 0xA3, -0xD1, 0x55, 0xC3, 0x4C, 0xE3, 0xA0, 0x49, 0xBC, 0x17, 0xB4, 0x31, 0x99, 0xBF, -0x75, 0xCB, 0xF2, 0xFB, 0x6B, 0x58, 0x52, 0x12, 0xC3, 0xBC, 0xED, 0xDC, 0x32, -0xBE, 0x9, 0x2C, 0xBB, 0x6A, 0x54, 0x6D, 0x9D, 0x5D, 0x97, 0xD3, 0xCC, 0x20, -0x31, 0x9C, 0x7E, 0x2B, 0x5C, 0x42, 0x9E, 0x2E, 0xCB, 0x41, 0x38, 0x84, 0x2, -0x3, 0x24, 0x75, 0x37, 0x23, 0x73, 0x38, 0x85, 0x0, 0x62, 0x42, 0x24, 0x76, -0x38, 0x88, 0x21, 0x31, 0x76, 0x74, 0x55, 0x51, 0x28, 0x34, 0x8, 0x41, 0x32, -0x67, 0x40, 0x11, 0x81, 0x62, 0x48, 0x27, 0x51, 0x85, 0x33, 0x61, 0x12, 0x22, -0x24, 0x30, 0x28, 0x75, 0x20, 0x3, 0x63, 0x11, 0x71, 0x88, 0x38, 0x88, 0x58, -0x84, 0x16, 0x66, 0x14, 0x22, 0x27, 0x28, 0x11, 0x44, 0x37, 0x76, 0x15, 0x24, -0x8, 0x56, 0x40, 0x13, 0x71, 0x74, 0x46, 0x88, 0x14, 0x37, 0x13, 0x0, 0x1, -0x48, 0x44, 0x4, 0x83, 0x67, 0x88, 0x16, 0x0, 0x13, 0x17, 0x6, 0x38, 0x18, -0x76, 0x15, 0x14, 0x67, 0x16, 0x76, 0x57, 0x24, 0x53, 0x86, 0x31, 0x34, 0x16, -0x34, 0x3, 0x8, 0x68, 0x65, 0x77, 0x36, 0x86, 0x37, 0x30, 0x76, 0x20, 0x51, -0x33, 0x82, 0x28, 0x72, 0x45, 0x35, 0x83, 0x6, 0x58, 0x58, 0x37, 0x71, 0x86, -0x0, 0x84, 0x18, 0x11, 0x54, 0x87, 0x12, 0x78, 0x75, 0x23, 0x45, 0x81, 0x17, -0x42, 0x1, 0x0, 0x34, 0x32, 0x55, 0x38, 0x88, 0x25, 0x52, 0x62, 0x5, 0x41, -0x86, 0x88, 0x67, 0x24, 0x81, 0x46, 0x74, 0x31, 0x53, 0x53, 0x45, 0x17, 0x26, -0x48, 0x85, 0x76, 0x24, 0x24, 0x36, 0x18, 0x50, 0x18, 0x18, 0x60, 0x76, 0x4, -0x87, 0x22, 0x0, 0x66, 0x74, 0x52, 0x18, 0x32, 0x7, 0x61, 0x27, 0x68, 0x70, -0x65, 0x78, 0x85, 0x66, 0x60, 0x5, 0x14, 0x77, 0x23, 0x74, 0x70, 0x41, 0x55, -0x12, 0x26, 0x86, 0x35, 0x28, 0x66, 0x30, 0x83, 0x42, 0x52, 0x26, 0x18, 0x34, -0x16, 0x48, 0x23, 0x35, 0x62, 0x37, 0x67, 0x82, 0x50, 0x1, 0x78, 0x70, 0x16, -0x11, 0x35, 0x58, 0x58, 0x8, 0x82, 0x55, 0x61, 0x85, 0x17, 0x46, 0x70, 0x77, -0x77, 0x37, 0x42, 0x35, 0x56, 0x53, 0x85, 0x7, 0x64, 0x13, 0x34, 0x51, 0x25, -0x78, 0x12, 0x21, 0x14, 0x74, 0x81, 0x32, 0x41, 0x0, 0x60, 0x78, 0x71, 0x22, -0x22, 0x56, 0x48, 0x57, 0x24, 0x65, 0x40, 0x36, 0x3, 0x3, 0x17, 0x86, 0x31, -0x44, 0x48, 0x55, 0x60, 0x55, 0x84, 0x68, 0x76, 0x16, 0x15, 0x40, 0x82, 0x64, -0x88, 0x47, 0x88, 0x44, 0x58, 0x46, 0x5, 0x2, 0x47, 0x27, 0x64, 0x20, 0x74, -0x14, 0x74, 0x2, 0x18, 0x21, 0x50, 0x42, 0x43, 0x14, 0x63, 0x5, 0x36, 0x8, -0x38, 0x80, 0x86, 0x80, 0x61, 0x15, 0x80, 0x56, 0x53, 0x13, 0x70, 0x64, 0x66, -0x20, 0x17, 0x21, 0x50, 0x68, 0x7, 0x53, 0x34, 0x73, 0x17, 0x50, 0x68, 0x72, -0x43, 0x2, 0x0, 0x80, 0x7, 0x37, 0x85, 0x72, 0x12, 0x87, 0x73, 0x46, 0x45, -0x56, 0x66, 0x2, 0x72, 0x70, 0x78, 0x34, 0x51, 0x65, 0x31, 0x77, 0x75, 0x52, -0x17, 0x82, 0x84, 0x34, 0x26, 0x51, 0x21, 0x31, 0x18, 0x33, 0x28, 0x84, 0x57, -0x10, 0x30, 0x47, 0x26, 0x27, 0x53, 0x58, 0x10, 0x73, 0x42, 0x67, 0x58, 0x27, -0x36, 0x56, 0x77, 0x25, 0x43, 0x87, 0x75, 0x65, 0x82, 0x51, 0x56, 0x60, 0x65, -0x70, 0x5, 0x7, 0x33, 0x48, 0x37, 0x82, 0x60, 0x11, 0x23, 0x18, 0x15, 0x22, -0x42, 0x10, 0x46, 0x81, 0x47, 0x44, 0x22, 0x73, 0x76, 0x28, 0x30, 0x63, 0x10, -0x24, 0x72, 0x12, 0x17, 0x78, 0x50, 0x1, 0x75, 0x57, 0x42, 0x88, 0x21, 0x22, -0x77, 0x68, 0x22, 0x43, 0x84, 0x14, 0x51, 0x73, 0x68, 0x54, 0x62, 0x8, 0x83, -0x75, 0x41, 0x10, 0x15, 0x14, 0x57, 0x73, 0x42, 0x13, 0x20, 0x52, 0x76, 0x72, -0x34, 0x18, 0x10, 0x0, 0x18, 0x17, 0x55, 0x30, 0x88, 0x47, 0x23, 0x0, 0x76, -0x44, 0x85, 0x25, 0x4, 0x3, 0x88, 0x0, 0x70, 0x10, 0x70, 0x1, 0x80, 0x12, -0x4, 0x73, 0x20, 0x72, 0x21, 0x24, 0x37, 0x4, 0x1, 0x63, 0x76, 0x4, 0x71, -0x30, 0x31, 0x17, 0x20, 0x18, 0x37, 0x23, 0x44, 0x3, 0x8, 0x77, 0x63, 0x73, -0x61, 0x43, 0x70, 0x11, 0x6, 0x84, 0x73, 0x26, 0x38, 0x78, 0x23, 0x61, 0x12, -0x45, 0x84, 0x76, 0x31, 0x23, 0x67, 0x37, 0x7, 0x73, 0x13, 0x46, 0x42, 0x51, -0x13, 0x12, 0x5, 0x15, 0x28, 0x57, 0x64, 0x62, 0x82, 0x42, 0x6, 0x83, 0x25, -0x12, 0x20, 0x40, 0x48, 0x21, 0x47, 0x73, 0x38, 0x13, 0x32, 0x10, 0x73, 0x36, -0x57, 0x3, 0x0, 0x31, 0x54, 0x78, 0x40, 0x23, 0x21, 0x14, 0x35, 0x13, 0x62, -0x83, 0x56, 0x35, 0x87, 0x44, 0x65, 0x74, 0x5, 0x66, 0x76, 0x26, 0x35, 0x17, -0x18, 0x67, 0x12, 0x6, 0x0, 0x42, 0x85, 0x71, 0x20, 0x62, 0x81, 0x22, 0x5, -0x76, 0x32, 0x77, 0x60, 0x65, 0x84, 0x64, 0x14, 0x60, 0x8, 0x55, 0x65, 0x21, -0x18, 0x8, 0x77, 0x72, 0x37, 0x70, 0x28, 0x24, 0x13, 0x18, 0x60, 0x83, 0x73, -0x33, 0x71, 0x16, 0x63, 0x72, 0x55, 0x64, 0x24, 0x11, 0x30, 0x84, 0x54, 0x33, -0x15, 0x33, 0x26, 0x66, 0x32, 0x35, 0x72, 0x52, 0x52, 0x35, 0x85, 0x85, 0x72, -0x5, 0x81, 0x84, 0x34, 0x78, 0x70, 0x65, 0x34, 0x10, 0x76, 0x76, 0x20, 0x76, -0x33, 0x33, 0x22, 0x76, 0x75, 0x28, 0x3, 0x4, 0x21, 0x28, 0x73, 0x3, 0x57, -0x72, 0x3, 0x35, 0x37, 0x66, 0x88, 0x23, 0x88, 0x27, 0x43, 0x32, 0x26, 0x5, -0x20, 0x36, 0x32, 0x78, 0x54, 0x83, 0x38, 0x86, 0x81, 0x78, 0x1, 0x63, 0x21, -0x75, 0x82, 0x1, 0x73, 0x18, 0x0, 0x42, 0x54, 0x67, 0x26, 0x52, 0x38, 0x18, -0x65, 0x87, 0x36, 0x86, 0x53, 0x84, 0x20, 0x6, 0x23, 0x62, 0x73, 0x4, 0x14, -0x83, 0x77, 0x0, 0x57, 0x86, 0x84, 0x70, 0x48, 0x2, 0x71, 0x28, 0x41, 0x42, -0x12, 0x13, 0x73, 0x43, 0x22, 0x65, 0x60, 0x72, 0x75, 0x28, 0x42, 0x17, 0x24, -0x67, 0x38, 0x27, 0x86, 0x58, 0x68, 0x25, 0x42, 0x2, 0x56, 0x62, 0x67, 0x5, -0x34, 0x54, 0x64, 0x68, 0x25, 0x15, 0x55, 0x88, 0x43, 0x58, 0x73, 0x77, 0x65, -0x46, 0x48, 0x36, 0x6, 0x86, 0x32, 0x80, 0x80, 0x18, 0x72, 0x2, 0x54, 0x54, -0x72, 0x10, 0x65, 0x70, 0x41, 0x63, 0x47, 0x35, 0x40, 0x75, 0x2, 0x70, 0x43, -0x18, 0x26, 0x78, 0x51, 0x52, 0x74, 0x43, 0x14, 0x51, 0x53, 0x77, 0x67, 0x53, -0x24, 0x11, 0x11, 0x57, 0x74, 0x18, 0x12, 0x27, 0x73, 0x30, 0x6, 0x42, 0x75, -0x16, 0x17, 0x58, 0x4, 0x81, 0x5, 0x48, 0x54, 0x78, 0x53, 0x71, 0x6, 0x28, -0x41, 0x63, 0x81, 0x67, 0x0, 0x18, 0x25, 0x24, 0x14, 0x70, 0x85, 0x70, 0x80, -0x72, 0x48, 0x23, 0x21, 0x47, 0x13, 0x74, 0x72, 0x4, 0x27, 0x20, 0x75, 0x6, -0x80, 0x12, 0x24, 0x18, 0x57, 0x75, 0x45, 0x33, 0x80, 0x47, 0x28, 0x25, 0x80, -0x86, 0x6, 0x67, 0x23, 0x51, 0x80, 0x6, 0x72, 0x34, 0x30, 0x16, 0x25, 0x15, -0x52, 0x16, 0x57, 0x77, 0x45, 0x1, 0x48, 0x83, 0x35, 0x58, 0x68, 0x77, 0x3, -0x20, 0x34, 0x70, 0x23, 0x66, 0x14, 0x85, 0x0, 0x5, 0x34, 0x32, 0x37, 0x83, -0x56, 0x45, 0x86, 0x32, 0x41, 0x56, 0x64, 0x83, 0x37, 0x77, 0x26, 0x80, 0x45, -0x16, 0x86, 0x64, 0x36, 0x85, 0x25, 0x16, 0x44, 0x47, 0x2, 0x62, 0x75, 0x86, -0x57, 0x82, 0x38, 0x34, 0x85, 0x21, 0x74, 0x15, 0x55, 0x26, 0x53, 0x16, 0x70, -0x82, 0x87, 0x17, 0x4, 0x63, 0x28, 0x21, 0x41, 0x61, 0x66, 0x16, 0x78, 0x37, -0x5, 0x81, 0x13, 0x26, 0x16, 0x56, 0x56, 0x85, 0x4, 0x72, 0x40, 0x64, 0x74, -0x13, 0x85, 0x20, 0x27, 0x14, 0x62, 0x72, 0x67, 0x70, 0x33, 0x25, 0x78, 0x48, -0x1, 0x17, 0x77, 0x14, 0x33, 0x41, 0x65, 0x5, 0x8, 0x0, 0x71, 0x44, 0x88, -0x8, 0x48, 0x2, 0x60, 0x12, 0x88, 0x5, 0x74, 0x56, 0x4, 0x77, 0x4, 0x52, -0x4, 0x31, 0x11, 0x81, 0x78, 0x88, 0x21, 0x11, 0x26, 0x51, 0x60, 0x67, 0x20, -0x37, 0x52, 0x1, 0x63, 0x85, 0x16, 0x68, 0x47, 0x65, 0x25, 0x2, 0x1, 0x18, -0x32, 0x0, 0x57, 0x33, 0x37, 0x38, 0x25, 0x27, 0x36, 0x21, 0x6, 0x40, 0x3, -0x74, 0x43, 0x24, 0x35, 0x86, 0x53, 0x88, 0x53, 0x16, 0x16, 0x2, 0x88, 0x44, -0x22, 0x25, 0x72, 0x63, 0x85, 0x17, 0x81, 0x56, 0x47, 0x16, 0x65, 0x2, 0x24, -0x5, 0x58, 0x55, 0x86, 0x72, 0x18, 0x21, 0x71, 0x86, 0x65, 0x61, 0x88, 0x85, -0x84, 0x70, 0x47, 0x27, 0x63, 0x73, 0x1, 0x26, 0x27, 0x85, 0x54, 0x85, 0x55, -0x45, 0x73, 0x30, 0x36, 0x44, 0x36, 0x45, 0x52, 0x43, 0x8, 0x14, 0x22, 0x64, -0x77, 0x36, 0x43, 0x14, 0x33, 0x66, 0x10, 0x56, 0x84, 0x42, 0x18, 0x77, 0x71, -0x27, 0x86, 0x84, 0x21, 0x26, 0x3, 0x22, 0x14, 0x47, 0x0, 0x51, 0x84, 0x28, -0x52, 0x66, 0x40, 0x66, 0x55, 0x85, 0x67, 0x2, 0x74, 0x6, 0x15, 0x72, 0x87, -0x40, 0x24, 0x71, 0x43, 0x74, 0x10, 0x27, 0x53, 0x42, 0x10, 0x3, 0x77, 0x1, -0x84, 0x8, 0x18, 0x22, 0x86, 0x71, 0x77, 0x48, 0x22, 0x42, 0x50, 0x66, 0x85, -0x34, 0x57, 0x88, 0x31, 0x81, 0x73, 0x66, 0x68, 0x75, 0x50, 0x10, 0x32, 0x73, -0x87, 0x57, 0x77, 0x40, 0x4, 0x3, 0x14, 0x87, 0x31, 0x38, 0x22, 0x65, 0x68, -0x68, 0x88, 0x10, 0x32, 0x71, 0x77, 0x5, 0x51, 0x76, 0x68, 0x40, 0x52, 0x36, -0x63, 0x2, 0x76, 0x84, 0x50, 0x76, 0x27, 0x6, 0x77, 0x58, 0x52, 0x52, 0x74, -0x78, 0x77, 0x77, 0x50, 0x30, 0x84, 0x54, 0x28, 0x53, 0x70, 0x82, 0x7, 0x21, -0x6, 0x64, 0x35, 0x62, 0x80, 0x55, 0x10, 0x71, 0x82, 0x2, 0x66, 0x81, 0x40, -0x57, 0x61, 0x7, 0x16, 0x2, 0x72, 0x67, 0x6, 0x24, 0x88, 0x23, 0x88, 0x63, -0x83, 0x81, 0x14, 0x40, 0x7, 0x17, 0x15, 0x20, 0x63, 0x76, 0x22, 0x75, 0x81, -0x70, 0x43, 0x81, 0x80, 0x43, 0x4, 0x51, 0x78, 0x40, 0x63, 0x36, 0x0, 0x77, -0x40, 0x24, 0x53, 0x11, 0x44, 0x65, 0x62, 0x56, 0x77, 0x20, 0x21, 0x25, 0x8, -0x25, 0x63, 0x34, 0x54, 0x76, 0x53, 0x6, 0x13, 0x1, 0x80, 0x25, 0x77, 0x44, -0x38, 0x17, 0x32, 0x36, 0x13, 0x32, 0x27, 0x0, 0x37, 0x60, 0x63, 0x74, 0x6, -0x52, 0x5, 0x72, 0x83, 0x83, 0x84, 0x28, 0x71, 0x15, 0x38, 0x17, 0x47, 0x8, -0x37, 0x42, 0x67, 0x86, 0x38, 0x62, 0x65, 0x26, 0x23, 0x84, 0x22, 0x38, 0x66, -0x6, 0xD9, 0x77, 0xF8, 0x41, 0xCB, 0x87, 0xD3, 0x3F, 0x76, 0xEB, 0x57, 0x71, -0xFF, 0xBF, 0x14, 0x3B, 0x4C, 0x53, 0x1, 0xA8, 0x24, 0xAC, 0xB4, 0x71, 0x4A, -0xD8, 0xAF, 0xCB, 0x45, 0x70, 0x6E, 0xF8, 0x89, 0xB6, 0x31, 0xA7, 0x8B, 0x4A, -0xCF, 0x6C, 0x42, 0x8E, 0x8, 0xCE, 0x55, 0x7D, 0x0, 0x1B, 0xA3, 0x3B, 0x9D, -0x2D, 0xC0, 0xF9, 0x85, 0x66, 0xA6, 0x3F, 0x5C, 0x77, 0xC0, 0xE1, 0x12, 0xF3, -0xEE, 0xBD, 0x4F, 0x9C, 0xB1, 0xD5, 0x1, 0x50, 0x22, 0x9C, 0xDD, 0xBF, 0xE9, -0xB7, 0xF5, 0x59, 0xC4, 0xB0, 0x9C, 0x2D, 0xB5, 0xA7, 0x4B, 0xB4, 0xD1, 0x2A, -0x91, 0x86, 0xC8, 0x28, 0x31, 0x73, 0xC0, 0x43, 0x2B, 0xBD, 0xDE, 0xDF, 0xA1, -0x2C, 0xAD, 0x9, 0x59, 0xB0, 0xF3, 0x95, 0x63, 0xA1, 0x7A, 0x88, 0x85, 0xA3, -0xFB, 0xF4, 0xD7, 0xF4, 0x1C, 0x68, 0xCD, 0x3F, 0x9C, 0x7A, 0xE5, 0xA9, 0x76, -0xB9, 0xC0, 0x89, 0xEE, 0x51, 0xD6, 0xB6, 0xF3, 0x4A, 0xF7, 0x5, 0xA1, 0x0, -0x6C, 0xF, 0x62, 0xC4, 0x65, 0x21, 0xB5, 0x9C, 0xD8, 0x77, 0x64, 0x94, 0x59, -0xBD, 0xA2, 0x14, 0x97, 0x45, 0x45, 0x58, 0xFF, 0x24, 0xD7, 0x9E, 0x47, 0x38, -0x32, 0xD6, 0x97, 0x98, 0xB7, 0xD7, 0xEF, 0x25, 0xDD, 0xFD, 0xAE, 0x91, 0xF7, -0x1E, 0x53, 0x9A, 0x8C, 0x11, 0xDE, 0xF3, 0xB6, 0x1D, 0xE0, 0x2A, 0xC8, 0x46, -0x47, 0xF8, 0x39, 0x59, 0xC4, 0x62, 0x8B, 0xD2, 0x7E, 0xDB, 0x23, 0xC5, 0xA3, -0x21, 0xF8, 0x16, 0xAE, 0x24, 0xFB, 0x19, 0x8D, 0x4D, 0xC3, 0x37, 0x96, 0x95, -0xA8, 0xA5, 0xA2, 0x8F, 0x4D, 0x77, 0xBC, 0x2E, 0xFB, 0xFE, 0xC8, 0xED, 0x76, -0x42, 0x1C, 0x2A, 0x3B, 0x41, 0xF7, 0xA0, 0xC5, 0xF3, 0xE9, 0x67, 0x7C, 0xC6, -0x88, 0xE7, 0x1A, 0x36, 0x65, 0x32, 0xFC, 0x15, 0x15, 0xF5, 0xA4, 0x9F, 0xA5, -0xF0, 0x67, 0xB1, 0xE6, 0x21, 0x4E, 0x9D, 0x29, 0x29, 0x50, 0xEB, 0x68, 0x36, -0x11, 0x9, 0xA5, 0x9C, 0xBD, 0x69, 0x1C, 0xA5, 0xB9, 0x8F, 0x68, 0x96, 0x1F, -0xA1, 0xDA, 0xFD, 0xF4, 0xED, 0xA2, 0xA6, 0xA7, 0xD2, 0x81, 0x9D, 0x91, 0x56, -0x9, 0xF4, 0x29, 0x24, 0x24, 0xA2, 0x8F, 0xC2, 0xB0, 0xEE, 0x2, 0xD9, 0x96, -0x8B, 0x9D, 0x9E, 0x1A, 0x48, 0xA7, 0x7A, 0x2D, 0x1D, 0x5A, 0xBF, 0x21, 0x60, -0x57, 0xB2, 0x28, 0x3, 0xBD, 0x4B, 0xEE, 0xE1, 0x71, 0x71, 0xF8, 0xC7, 0x3B, -0x1F, 0x2F, 0x6C, 0x2C, 0xBF, 0x1C, 0x51, 0x32, 0xFF, 0xF6, 0x3B, 0x53, 0x57, -0xBD, 0xC9, 0x9A, 0x58, 0xB4, 0xEA, 0x6, 0xBC, 0xDB, 0xB2, 0x2E, 0x86, 0x5D, -0xBB, 0x6A, 0x44, 0xF1, 0x8C, 0x4A, 0x6F, 0x4A, 0x8D, 0xEA, 0x93, 0x19, 0x36, -0xAC, 0x41, 0xA9, 0x92, 0x26, 0x4E, 0x8, 0xA5, 0xA5, 0xE9, 0xC6, 0xBD, 0xB6, -0xC2, 0x4F, 0xFF, 0xD1, 0xA5, 0x89, 0x30, 0xBF, 0x82, 0xE5, 0xEF, 0x1C, 0x47, -0x4B, 0xC, 0x3C, 0xFB, 0x46, 0x9D, 0xDA, 0x30, 0x35, 0xF8, 0x4, 0x9A, 0xD2, -0x60, 0xB7, 0x2C, 0x92, 0x1A, 0xB7, 0xCC, 0xEC, 0x1C, 0x5E, 0xED, 0x41, 0xCA, -0x11, 0xA1, 0x61, 0xDD, 0x6B, 0x4C, 0xA3, 0x1D, 0x95, 0x2A, 0x1A, 0x76, 0xC4, -0x35, 0xE5, 0xA9, 0x75, 0xCD, 0x20, 0x70, 0x91, 0xB0, 0xD3, 0x0, 0x70, 0x9B, -0xE9, 0xDC, 0xB3, 0xC7, 0x72, 0x62, 0xB7, 0xAD, 0x1, 0x4F, 0x6D, 0x23, 0x19, -0x67, 0xD8, 0xE8, 0x78, 0x84, 0x2E, 0xF1, 0xF8, 0x7A, 0x88, 0x13, 0xF2, 0xAA, -0x56, 0x8, 0xE7, 0x69, 0xE5, 0xE4, 0x12, 0x71, 0xBE, 0xFF, 0x9D, 0x94, 0x6D, -0xCA, 0xD2, 0xB5, 0x2A, 0x47, 0xAC, 0xCA, 0x6E, 0x3F, 0x27, 0x47, 0xF8, 0x6C, -0xBA, 0x8E, 0x61, 0x6C, 0xFB, 0x11, 0x50, 0x3D, 0x2E, 0x75, 0x28, 0xFA, 0x3A, -0xAD, 0x5B, 0x4B, 0x7A, 0x21, 0x35, 0x6B, 0x9E, 0xE1, 0xBE, 0xA0, 0xF9, 0x6C, -0x13, 0xE3, 0xC7, 0x84, 0xEB, 0x60, 0x76, 0x8F, 0x33, 0x8C, 0x57, 0xE1, 0x35, -0x2A, 0x1B, 0x5B, 0xD9, 0xA3, 0x77, 0x22, 0x93, 0x48, 0xB1, 0xF2, 0xA5, 0xB1, -0xCA, 0x35, 0x4D, 0x7A, 0x10, 0x0, 0xFB, 0x2E, 0xCD, 0x97, 0x80, 0x23, 0x6C, -0xD8, 0xA5, 0x49, 0x8D, 0xB3, 0x46, 0x5D, 0xEA, 0xE8, 0xF5, 0xFD, 0xDA, 0xE3, -0x9E, 0xDE, 0xF0, 0xB2, 0xF7, 0x5C, 0x82, 0x10, 0x9E, 0xC2, 0x4B, 0x4E, 0xD5, -0x45, 0x54, 0x15, 0xB1, 0xA5, 0xA7, 0xE5, 0xE0, 0xA5, 0xFE, 0x99, 0xB2, 0x6B, -0x30, 0x90, 0x55, 0xE1, 0xAF, 0x4, 0xB2, 0x15, 0x18, 0x60, 0x26, 0x99, 0x98, -0x3E, 0x67, 0xBC, 0x14, 0x45, 0x37, 0x2A, 0xA3, 0x23, 0x58, 0xCA, 0x82, 0x1C, -0x98, 0x7C, 0xC4, 0xB1, 0xE2, 0xED, 0xE5, 0xDF, 0x41, 0xDC, 0x7D, 0x13, 0xDF, -0xC1, 0xC1, 0xA7, 0xE, 0x24, 0x3D, 0xA2, 0x9D, 0x95, 0x44, 0x9, 0x7A, 0x42, -0x2B, 0x0, 0x23, 0x1C, 0x3D, 0xBC, 0x3E, 0x2B, 0x67, 0x6F, 0xB4, 0xC2, 0x49, -0xEB, 0xD, 0xFF, 0x6D, 0x19, 0x34, 0xBF, 0xDE, 0x2A, 0x9, 0x6C, 0x2F, 0x2B, -0x7D, 0xDE, 0x17, 0x54, 0x16, 0xEF, 0x4, 0x86, 0x89, 0xCA, 0x67, 0xA4, 0xE7, -0xBA, 0xF9, 0x7E, 0x8A, 0x42, 0xB2, 0xEB, 0x4F, 0xE8, 0x7B, 0xAD, 0x71, 0xBC, -0x1C, 0xF, 0x1D, 0x40, 0xB1, 0x84, 0xB2, 0x46, 0x46, 0xFB, 0x6A, 0xA7, 0x67, -0x30, 0x9B, 0xD0, 0x1A, 0x7A, 0xC1, 0xE9, 0xE7, 0x1, 0xA4, 0x1B, 0xC9, 0xE, -0x79, 0x6C, 0xE8, 0x46, 0x47, 0xCF, 0xA, 0x64, 0x42, 0xB1, 0xB1, 0x70, 0xB0, -0xB6, 0x6E, 0xDD, 0x93, 0xBA, 0x56, 0x78, 0xBA, 0x63, 0x87, 0x7F, 0x6E, 0x36, -0xC6, 0xFF, 0x90, 0xF5, 0xFC, 0xEE, 0x76, 0x61, 0x5C, 0x53, 0xD4, 0x4C, 0xE4, -0x9C, 0x59, 0xFF, 0x6B, 0x59, 0x44, 0x8E, 0x60, 0xDF, 0xFA, 0x25, 0x63, 0x4, -0xD0, 0xB6, 0x36, 0xF8, 0xF9, 0xB2, 0xD9, 0xDE, 0xD6, 0x29, 0xCD, 0x15, 0x90, -0x47, 0x8F, 0xCA, 0x5C, 0x1D, 0x42, 0x8D, 0x47, 0xF0, 0x72, 0xD5, 0x9, 0x92, -0x72, 0xE5, 0xB4, 0x2A, 0xAB, 0xD9, 0x6, 0x40, 0xDD, 0x3E, 0x7D, 0x85, 0x8, -0x7E, 0x12, 0x7E, 0x6A, 0xD, 0xB7, 0x9F, 0x98, 0xC7, 0x47, 0x63, 0xBB, 0xC6, -0x3C, 0x7, 0x68, 0x5F, 0xC3, 0x82, 0xAC, 0x6A, 0xD6, 0x4D, 0x29, 0x68, 0xFF, -0xD5, 0x46, 0xD4, 0x87, 0xE6, 0x4A, 0xFF, 0x22, 0x93, 0x2A, 0x4, 0x8, 0xA7, -0x9B, 0xF3, 0xA1, 0x7E, 0x4C, 0x2C, 0xFF, 0xEA, 0x7D, 0x97, 0x4B, 0x5B, 0x8F, -0xDE, 0x6F, 0x0, 0x80, 0xAB, 0x62, 0x96, 0x5E, 0x3A, 0x25, 0x39, 0xD3, 0x65, -0x9B, 0x7, 0x1D, 0x67, 0x80, 0x9A, 0x9B, 0xEF, 0x84, 0xF1, 0x66, 0xCF, 0xEB, -0x83, 0xBE, 0x5F, 0xA3, 0x7E, 0x92, 0x36, 0xAF, 0x80, 0xBE, 0x20, 0x88, 0x23, -0x9A, 0x23, 0x98, 0xB4, 0x90, 0xC7, 0x27, 0x6A, 0xA9, 0xBC, 0xC1, 0x71, 0x4D, -0xFF, 0x1B, 0x60, 0xF8, 0xA5, 0xE1, 0xB0, 0x5A, 0x6A, 0xC7, 0x87, 0xF, 0xB9, -0x3C, 0x99, 0xB0, 0x49, 0x65, 0x37, 0x28, 0xE7, 0x11, 0xC, 0xB8, 0xB9, 0x6B, -0xDC, 0x3C, 0x28, 0xF9, 0xFA, 0x96, 0x1A, 0x84, 0xDF, 0x20, 0x1E, 0xC, 0x8C, -0x5B, 0xA2, 0x22, 0x3E, 0x5B, 0x74, 0x38, 0x72, 0x45, 0x8D, 0xFA, 0x7D, 0x9F, -0xC3, 0x1F, 0x49, 0xA, 0xD9, 0x32, 0x8E, 0x2B, 0xDC, 0x86, 0x91, 0x15, 0xE6, -0xEA, 0xD4, 0x87, 0xE4, 0x6C, 0xE0, 0x31, 0xB4, 0xBF, 0x31, 0xB6, 0xD1, 0x94, -0xF8, 0x4E, 0x4B, 0xF3, 0x22, 0x7F, 0x88, 0x2F, 0xB2, 0x1F, 0x8E, 0xCA, 0x7, -0x6C, 0xCE, 0xAE, 0x25, 0x82, 0xB6, 0xE1, 0x30, 0x91, 0xE8, 0xB3, 0xD2, 0x24, -0x11, 0x31, 0xC6, 0x58, 0xC5, 0xB3, 0xBC, 0x45, 0xA8, 0x41, 0x6, 0x31, 0x89, -0xC9, 0x43, 0x2, 0x63, 0x9F, 0xEA, 0x9B, 0x69, 0x44, 0x8F, 0xD6, 0x44, 0x70, -0xCB, 0x83, 0x52, 0xDE, 0x39, 0x16, 0x77, 0x79, 0x7F, 0x23, 0xAC, 0x5C, 0x5F, -0x9F, 0x2B, 0xD2, 0x28, 0x73, 0xC0, 0x8D, 0x88, 0x7F, 0xEF, 0xA5, 0x30, 0xE6, -0x8B, 0x35, 0x4C, 0xD1, 0xA5, 0x6E, 0xE7, 0x4F, 0x19, 0x31, 0x78, 0x1, 0x98, -0xC5, 0xA6, 0x3D, 0x1E, 0xE8, 0x78, 0x85, 0x19, 0xDD, 0xAC, 0x8C, 0xBF, 0x1, -0xEE, 0x44, 0xA1, 0xD1, 0xA, 0xAB, 0x13, 0x99, 0x9D, 0x45, 0x73, 0x7, 0xF9, -0xD7, 0x9, 0x97, 0x93, 0x0, 0x94, 0x2, 0x68, 0xF9, 0xE8, 0x88, 0xC4, 0x9E, -0x53, 0xD6, 0x74, 0xF7, 0x9A, 0xAD, 0xC7, 0xE2, 0x1E, 0xBE, 0x57, 0x7B, 0xD, -0x5D, 0xE6, 0x7D, 0x3C, 0xF5, 0xF0, 0xE6, 0x1, 0xE5, 0x95, 0x1E, 0xA8, 0xB0, -0xA4, 0x92, 0xF4, 0xB0, 0x64, 0x7E, 0x63, 0x72, 0x52, 0xE7, 0x75, 0x30, 0x84, -0xE7, 0x9F, 0x51, 0x68, 0xA6, 0xB8, 0xFE, 0x2B, 0xF2, 0x58, 0xA4, 0x9, 0x2F, -0xB9, 0x0, 0xEB, 0xB0, 0x34, 0xD7, 0x5F, 0x3E, 0x3E, 0x76, 0xC1, 0x5D, 0x11, -0xCC, 0xB2, 0x4A, 0xBB, 0x7, 0x27, 0xFC, 0x8B, 0x47, 0xEC, 0x44, 0x4A, 0x8C, -0x6D, 0xE8, 0x42, 0x29, 0xAD, 0xED, 0x45, 0x3F, 0x2C, 0xDA, 0x3F, 0x4F, 0x9A, -0xDE, 0x54, 0xEB, 0x1D, 0xE4, 0x31, 0x54, 0xF7, 0xAF, 0x58, 0x81, 0x72, 0xED, -0xB9, 0xEC, 0x9, 0x2B, 0x38, 0xB1, 0xE5, 0x94, 0xE5, 0xC6, 0xE0, 0x7E, 0x3B, -0x48, 0x56, 0xAE, 0x15, 0x8C, 0xF7, 0xE5, 0x89, 0x23, 0xB0, 0xA9, 0x78, 0xC5, -0x5E, 0x3C, 0xB0, 0x3B, 0x1F, 0x1E, 0xA7, 0x34, 0x2D, 0xB3, 0x6E, 0xCC, 0x1A, -0xAB, 0x8E, 0x80, 0x39, 0xF5, 0x8A, 0x2F, 0x66, 0x4C, 0xF5, 0xDA, 0xCE, 0x2E, -0x6E, 0xCC, 0x12, 0xE4, 0xDB, 0xD5, 0x94, 0xBA, 0x18, 0xC9, 0x1E, 0xB4, 0xD1, -0x18, 0x6A, 0x5E, 0x37, 0x6A, 0x3A, 0x78, 0x70, 0x50, 0x7D, 0xC9, 0x65, 0x4D, -0x31, 0xE8, 0xB0, 0x89, 0xA5, 0xAA, 0x3D, 0x1, 0x46, 0x53, 0x84, 0xBC, 0xEE, -0x78, 0x38, 0x25, 0x99, 0x2D, 0xA7, 0x7B, 0xAA, 0x6, 0xB8, 0x28, 0xE9, 0x1, -0xD2, 0xDE, 0x84, 0x56, 0x2, 0xBA, 0x49, 0xFB, 0xA2, 0xAD, 0x8E, 0xEC, 0x73, -0xA, 0xF4, 0xB8, 0x24, 0xB8, 0xD0, 0x75, 0xC8, 0xB5, 0xCF, 0xF5, 0xE8, 0xC7, -0x4B, 0xDF, 0xEC, 0x43, 0xBC, 0x59, 0xD8, 0xFD, 0xA9, 0xC5, 0x26, 0xD9, 0x65, -0xB7, 0xB8, 0x22, 0x1E, 0x2E, 0x70, 0xD3, 0x86, 0xF4, 0xF4, 0x84, 0x81, 0x5A, -0x3D, 0x33, 0xCC, 0x82, 0x45, 0x99, 0xC1, 0x1B, 0x47, 0xCD, 0xEF, 0xAE, 0x19, -0xA0, 0x1C, 0xA5, 0x7D, 0x74, 0x1F, 0x7C, 0xA3, 0x4, 0x3D, 0x97, 0x70, 0x8F, -0x2D, 0xCA, 0x6D, 0xAD, 0x2C, 0x9A, 0x53, 0x45, 0x51, 0xA1, 0xE3, 0x47, 0x2C, -0x80, 0x7D, 0x2, 0x7B, 0x8A, 0xD4, 0x7A, 0x8B, 0x58, 0x11, 0x81, 0x60, 0x2A, -0xC4, 0x4D, 0x26, 0xE, 0xAC, 0x41, 0x89, 0x5E, 0x49, 0xC9, 0xC5, 0x39, 0x9B, -0xCA, 0xD3, 0xB3, 0xE3, 0x19, 0xE7, 0xF2, 0xE6, 0x57, 0x1E, 0x2A, 0x5A, 0x29, -0x78, 0x14, 0xAD, 0x97, 0x7A, 0x2, 0xE5, 0xD8, 0x15, 0x8C, 0xEC, 0xA6, 0x3, -0x9A, 0x11, 0xF9, 0x95, 0x31, 0xED, 0xF2, 0x8C, 0xF1, 0xEF, 0x6B, 0xA5, 0x39, -0xAD, 0xF7, 0x8, 0xDA, 0x1D, 0x4D, 0xC6, 0xAF, 0x93, 0x60, 0xE7, 0x57, 0x31, -0xE4, 0x9E, 0x70, 0x66, 0xD5, 0x8A, 0xB4, 0x3C, 0x15, 0x6F, 0x95, 0xAF, 0xA9, -0x6B, 0xD5, 0xE, 0xDE, 0x37, 0x1D, 0x4C, 0xFA, 0x71, 0xCA, 0xAA, 0x96, 0x5, -0x13, 0x38, 0x13, 0x6D, 0xE5, 0xC6, 0x3F, 0xC5, 0x60, 0xFC, 0xFC, 0xCE, 0xA4, -0xDB, 0xC9, 0x91, 0xE3, 0x59, 0x2C, 0x9D, 0xB0, 0x76, 0xB8, 0x9A, 0x7D, 0xF4, -0x96, 0x37, 0x4, 0xEE, 0xCF, 0x8C, 0xE2, 0x5D, 0x36, 0xE8, 0xAA, 0x4E, 0x4B, -0x7B, 0xD0, 0x4D, 0xB4, 0x24, 0xA8, 0x42, 0x12, 0xD, 0xDC, 0xA, 0xAF, 0xBB, -0x52, 0xE6, 0xF2, 0xD1, 0x7, 0xE4, 0x15, 0x16, 0x36, 0xBA, 0x43, 0xD2, 0x3B, -0x17, 0x66, 0xFF, 0x6D, 0x75, 0x7F, 0x1F, 0xC7, 0xE1, 0x5C, 0x27, 0xE6, 0xF3, -0x92, 0x7D, 0x54, 0x96, 0xC6, 0x5C, 0x5A, 0x5D, 0xFB, 0x94, 0xBD, 0x5A, 0x79, -0x7, 0xCF, 0xFC, 0x1E, 0x4F, 0x87, 0x7B, 0x7E, 0xFC, 0x25, 0x90, 0x62, 0x34, -0x94, 0x92, 0xFB, 0x83, 0xB1, 0xCE, 0xA2, 0x5B, 0x6A, 0xAB, 0x98, 0x23, 0x50, -0xD4, 0x14, 0xB3, 0x8, 0xD6, 0x45, 0xAB, 0xCF, 0x7C, 0xB, 0x94, 0xB7, 0x56, -0x63, 0x43, 0x1A, 0x46, 0x3C, 0xF3, 0x3D, 0x7, 0x19, 0x27, 0x9D, 0x3, 0x3E, -0x48, 0x85, 0xF7, 0xF5, 0x1D, 0x5F, 0xD8, 0x14, 0xEE, 0x3A, 0x9D, 0xDD, 0xF6, -0x1D, 0x7B, 0x3, 0x45, 0x30, 0x84, 0x51, 0xE2, 0x54, 0xBB, 0x96, 0x21, 0xD6, -0x93, 0x94, 0x46, 0x8, 0xAF, 0x6C, 0x32, 0x1F, 0x9F, 0x6B, 0xDF, 0x72, 0x80, -0xFB, 0xA8, 0xF3, 0xCD, 0x32, 0x52, 0x46, 0x4A, 0xAC, 0xB1, 0xA0, 0x25, 0x64, -0x8D, 0x41, 0xA7, 0x9C, 0xD9, 0x2D, 0xAE, 0x83, 0x90, 0xC9, 0xF9, 0x26, 0x91, -0xB2, 0xE3, 0x4, 0x6E, 0xA9, 0x46, 0x96, 0x5E, 0xA1, 0x5E, 0xEB, 0x2, 0xCB, -0x2, 0x1B, 0x21, 0xF7, 0x78, 0xB0, 0x10, 0x8F, 0x29, 0x9C, 0xFB, 0xAC, 0xFE, -0xC8, 0x8A, 0x79, 0x4, 0xC6, 0xED, 0xD, 0x9D, 0x27, 0xE5, 0x11, 0x65, 0x66, -0x14, 0xCD, 0xD, 0xCD, 0x85, 0x1D, 0x51, 0xE1, 0x64, 0xBC, 0x7E, 0x91, 0xD0, -0x54, 0xAB, 0x13, 0xFC, 0xF1, 0x22, 0x7C, 0x86, 0x17, 0xE6, 0x76, 0x76, 0xD6, -0x86, 0x5A, 0x3E, 0x92, 0xE6, 0x5F, 0x2E, 0x2F, 0xFC, 0xF0, 0xA8, 0x24, 0x91, -0xDF, 0xA8, 0x2, 0x72, 0xDC, 0x8A, 0xA6, 0x86, 0x85, 0xBE, 0xC6, 0x78, 0xFC, -0xDD, 0xC, 0xB0, 0x4B, 0x4D, 0xD4, 0xBE, 0x24, 0xB9, 0x3, 0x3, 0x54, 0x9F, -0xAB, 0x6, 0x5, 0x91, 0x4E, 0x41, 0xE9, 0x7E, 0x99, 0x18, 0x3C, 0xB1, 0x96, -0xF0, 0x99, 0x6A, 0xEC, 0xF6, 0x60, 0x7E, 0xE2, 0xD3, 0x6E, 0xED, 0xA8, 0xFC, -0x5F, 0x7, 0x34, 0x65, 0x4A, 0x27, 0x5C, 0x64, 0xD3, 0xF8, 0xA8, 0x6C, 0x92, -0x89, 0x6B, 0x21, 0xAD, 0x7D, 0x35, 0x17, 0xB0, 0x60, 0x93, 0xFA, 0x3E, 0x35, -0x52, 0x9C, 0x8E, 0x38, 0xA1, 0x11, 0xA2, 0x70, 0xB9, 0x8A, 0x8E, 0x3C, 0xCD, -0x57, 0x2, 0x48, 0x1, 0x3D, 0xFC, 0xA1, 0x75, 0x95, 0xF9, 0x90, 0xD, 0x3A, -0xF5, 0x6B, 0xBB, 0xDC, 0xC6, 0x2C, 0x82, 0x2B, 0xE4, 0x4C, 0x2, 0xDC, 0xD0, -0x80, 0x4F, 0x93, 0x22, 0x8D, 0xED, 0xE3, 0x92, 0x26, 0xC7, 0x64, 0x47, 0xDC, -0x85, 0x65, 0x9, 0x3D, 0x5B, 0x82, 0x34, 0x2F, 0x52, 0x93, 0x42, 0xD8, 0x68, -0x35, 0xF8, 0xA9, 0xCC, 0x87, 0x42, 0x9, 0x99, 0xFE, 0x5F, 0x70, 0xBB, 0x16, -0xD5, 0xFC, 0x60, 0x5D, 0x17, 0x92, 0x63, 0xBA, 0x1B, 0x69, 0xD5, 0xDC, 0x62, -0x2A, 0x66, 0x6, 0xD7, 0xD0, 0x46, 0x29, 0xC5, 0x0, 0x1, 0x77, 0x7D, 0xB2, -0x9B, 0x69, 0x7F, 0xCE, 0xBD, 0xFD, 0xC8, 0x11, 0x1C, 0x4E, 0x30, 0x6A, 0x66, -0x5F, 0x17, 0xD7, 0xCB, 0x91, 0x7E, 0x7F, 0xA7, 0x4C, 0xCE, 0xDC, 0xF2, 0x5B, -0x3C, 0x6A, 0xAB, 0x4B, 0x56, 0xD6, 0x4B, 0x9A, 0xA2, 0x88, 0xB, 0xC6, 0x7C, -0x10, 0x8, 0xF5, 0x8E, 0xD5, 0xF2, 0x38, 0x78, 0x9, 0xBC, 0x7F, 0x23, 0x4E, -0x67, 0xBD, 0x88, 0xDC, 0x91, 0xB3, 0xFE, 0x6B, 0x99, 0x99, 0xE1, 0xF3, 0xB6, -0xC1, 0x6E, 0x44, 0xBA, 0xEF, 0xE0, 0xBF, 0xBD, 0x2F, 0xBA, 0x92, 0xFB, 0xA5, -0x29, 0xB, 0x33, 0x9E, 0xAD, 0x66, 0x85, 0x3F, 0xD0, 0x61, 0x9A, 0x44, 0xA6, -0xDF, 0x96, 0xA, 0x1D, 0x78, 0xC2, 0x8D, 0x64, 0x86, 0xD9, 0xC, 0xBF, 0x21, -0x14, 0xA2, 0x96, 0x2C, 0x5B, 0x13, 0x1B, 0xA6, 0xDB, 0xD5, 0xE6, 0xD7, 0xC4, -0xFE, 0x52, 0xE3, 0x77, 0x8B, 0x37, 0x47, 0x24, 0x57, 0x94, 0x70, 0x55, 0x53, -0xC3, 0x8, 0x8F, 0xDA, 0x20, 0xBF, 0x85, 0x97, 0x74, 0x79, 0xB, 0x0, 0xB, -0x1E, 0xF1, 0x1A, 0x83, 0x40, 0xC7, 0x51, 0xFD, 0xDD, 0x3D, 0xB7, 0xC, 0x92, -0x72, 0x16, 0xCA, 0xFA, 0x8E, 0x43, 0x9E, 0xA3, 0x73, 0xFF, 0x12, 0x47, 0x26, -0x64, 0xA8, 0xC6, 0x36, 0xC4, 0xB0, 0x77, 0x9A, 0x84, 0xEC, 0x1D, 0xCD, 0xF3, -0x91, 0x48, 0x2A, 0xAD, 0x37, 0xEE, 0x47, 0xA4, 0x47, 0xD6, 0x26, 0x64, 0xAA, -0xE0, 0x6B, 0x25, 0xFE, 0xD5, 0xB, 0x7, 0x65, 0x30, 0xAB, 0xFC, 0xC0, 0xB7, -0x90, 0x8F, 0xA9, 0x3F, 0xC8, 0x9, 0x9A, 0xF7, 0x8F, 0x33, 0x8A, 0xB3, 0xEE, -0xFC, 0xA3, 0x6E, 0x50, 0xA, 0x84, 0xAB, 0xF8, 0x1F, 0x89, 0xEB, 0x5D, 0xDE, -0x35, 0x4B, 0x4E, 0x23, 0x8D, 0x52, 0x47, 0x54, 0x3F, 0x9B, 0x9B, 0x4F, 0xBD, -0xEB, 0x36, 0x81, 0x33, 0xB, 0x86, 0x9E, 0x19, 0x14, 0xC0, 0x49, 0xB5, 0x74, -0xEB, 0x79, 0xF7, 0xC2, 0x34, 0xF2, 0xEF, 0x10, 0x3A, 0xB0, 0x17, 0x8D, 0x16, -0x71, 0x2, 0xEE, 0x8A, 0x4C, 0x5B, 0xF1, 0xC7, 0x2F, 0xDE, 0x57, 0x24, 0x5F, -0x5D, 0x1A, 0x1A, 0xC5, 0xBB, 0xFB, 0xD3, 0x5F, 0xB0, 0xB5, 0xCF, 0x1A, 0x1C, -0x68, 0x84, 0x78, 0x23, 0x80, 0x84, 0x47, 0x3, 0xE8, 0x4B, 0x45, 0x9B, 0x5B, -0xD9, 0x9F, 0x3, 0x9B, 0xC9, 0xDF, 0xAF, 0xDD, 0x51, 0xBF, 0xCE, 0x59, 0xD7, -0x79, 0x67, 0x61, 0xCF, 0x55, 0x2A, 0x11, 0xD2, 0x42, 0xB7, 0x4A, 0x62, 0x1D, -0xC4, 0xDC, 0x6D, 0xBB, 0xC4, 0x9A, 0x60, 0xE2, 0x73, 0x40, 0x47, 0x60, 0x3E, -0x5F, 0x53, 0x37, 0xAE, 0x5B, 0x9E, 0x4D, 0xF7, 0xE4, 0x7B, 0x61, 0xA, 0x86, -0xA8, 0xDC, 0x2D, 0x65, 0x75, 0xE2, 0x8A, 0x2D, 0xC8, 0x73, 0xD8, 0x18, 0xAF, -0xAC, 0xC6, 0x6C, 0xDA, 0x67, 0x28, 0x52, 0xE8, 0xAE, 0xE4, 0x66, 0xF1, 0xD1, -0xC8, 0x1B, 0xD0, 0x9F, 0xA1, 0x42, 0xE, 0xC9, 0x75, 0x1E, 0x39, 0x2E, 0xD2, -0x43, 0x1, 0x76, 0x3B, 0xF7, 0x88, 0xAF, 0xC0, 0x3C, 0x96, 0xD, 0xF3, 0xE, -0x42, 0xFC, 0x80, 0xA, 0xAE, 0xF8, 0x3A, 0x16, 0x87, 0xA0, 0x5F, 0x7D, 0x5A, -0x4C, 0x56, 0x90, 0xCE, 0x2B, 0x82, 0x5A, 0x2B, 0x49, 0xD5, 0x2C, 0x11, 0x83, -0x96, 0xB9, 0xF6, 0xDB, 0xA9, 0x66, 0xD6, 0xAC, 0x9B, 0x9, 0x3C, 0x6C, 0x15, -0xE3, 0x1D, 0xF6, 0xF7, 0xEE, 0x9F, 0xA, 0xC5, 0x91, 0x14, 0x33, 0x4B, 0xDB, -0xC4, 0xEE, 0xC, 0xFB, 0xE4, 0xD1, 0x43, 0xC2, 0x1B, 0xC3, 0x2, 0x9B, 0x6B }; + 0x30, 0x82, 0x0F, 0xD8, 0x02, 0x01, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x12, 0x04, 0x82, 0x0F, 0xC4, + 0x04, 0x82, 0x0F, 0xC0, 0x48, 0x68, 0x3D, 0x91, 0x97, 0x8E, 0x31, 0xEB, + 0x3D, 0xDD, 0xB8, 0xB0, 0x47, 0x34, 0x82, 0xD2, 0xB8, 0x8A, 0x5F, 0x62, + 0x59, 0x49, 0xFD, 0x8F, 0x58, 0xA5, 0x61, 0xE6, 0x96, 0xBD, 0x4C, 0x27, + 0xD8, 0x53, 0xFA, 0x69, 0xB8, 0x19, 0x90, 0x23, 0xE8, 0xCD, 0x67, 0x8D, + 0xD9, 0xFA, 0xBF, 0x90, 0x47, 0x64, 0x6F, 0xFD, 0x0C, 0xB3, 0xCC, 0x7F, + 0x79, 0x58, 0x05, 0xA7, 0x1E, 0x70, 0xD2, 0x37, 0x1B, 0x05, 0x63, 0xE3, + 0xCD, 0x33, 0x46, 0x14, 0x9C, 0x8C, 0x9E, 0xBC, 0xF2, 0x3B, 0x0A, 0x4E, + 0x5A, 0x90, 0x0E, 0xEA, 0x9C, 0x65, 0x62, 0x79, 0x0A, 0x7C, 0x63, 0xE3, + 0x86, 0x63, 0xDA, 0xA2, 0xDD, 0xDB, 0x6E, 0x48, 0x0D, 0xC4, 0x05, 0xA1, + 0xE7, 0x01, 0x94, 0x8B, 0x74, 0x84, 0x1E, 0xF5, 0xCC, 0x1C, 0x3F, 0x2B, + 0xF3, 0x27, 0x97, 0x2E, 0x95, 0x10, 0x51, 0x0C, 0xD5, 0x37, 0x5E, 0xCC, + 0x08, 0x55, 0x71, 0x77, 0x11, 0x87, 0x22, 0x21, 0x86, 0x23, 0x81, 0x00, + 0x04, 0x24, 0x77, 0x80, 0x61, 0x47, 0x50, 0x07, 0x50, 0x17, 0x17, 0x03, + 0x55, 0x04, 0x51, 0x51, 0x25, 0x47, 0x18, 0x38, 0x04, 0x61, 0x75, 0x72, + 0x22, 0x44, 0x10, 0x88, 0x68, 0x60, 0x86, 0x46, 0x01, 0x27, 0x47, 0x56, + 0x71, 0x80, 0x87, 0x06, 0x66, 0x86, 0x43, 0x32, 0x44, 0x41, 0x22, 0x04, + 0x36, 0x38, 0x66, 0x75, 0x02, 0x82, 0x36, 0x34, 0x24, 0x43, 0x22, 0x05, + 0x73, 0x64, 0x10, 0x64, 0x55, 0x54, 0x77, 0x22, 0x75, 0x56, 0x81, 0x43, + 0x36, 0x14, 0x62, 0x55, 0x08, 0x20, 0x64, 0x37, 0x68, 0x54, 0x68, 0x75, + 0x43, 0x53, 0x75, 0x10, 0x68, 0x71, 0x83, 0x33, 0x80, 0x54, 0x75, 0x05, + 0x25, 0x80, 0x75, 0x28, 0x18, 0x84, 0x38, 0x11, 0x08, 0x72, 0x60, 0x20, + 0x20, 0x08, 0x58, 0x83, 0x01, 0x83, 0x61, 0x13, 0x82, 0x82, 0x12, 0x06, + 0x17, 0x11, 0x57, 0x87, 0x68, 0x78, 0x88, 0x78, 0x64, 0x37, 0x54, 0x60, + 0x16, 0x57, 0x15, 0x50, 0x84, 0x71, 0x88, 0x66, 0x07, 0x27, 0x32, 0x88, + 0x06, 0x64, 0x74, 0x18, 0x56, 0x76, 0x21, 0x80, 0x31, 0x82, 0x76, 0x64, + 0x15, 0x78, 0x24, 0x50, 0x25, 0x64, 0x66, 0x43, 0x11, 0x35, 0x04, 0x36, + 0x47, 0x80, 0x12, 0x66, 0x73, 0x14, 0x30, 0x11, 0x66, 0x06, 0x55, 0x86, + 0x47, 0x18, 0x36, 0x88, 0x63, 0x50, 0x38, 0x47, 0x86, 0x11, 0x01, 0x20, + 0x23, 0x56, 0x11, 0x61, 0x37, 0x86, 0x07, 0x85, 0x32, 0x12, 0x40, 0x07, + 0x54, 0x78, 0x82, 0x30, 0x43, 0x66, 0x61, 0x16, 0x60, 0x42, 0x55, 0x41, + 0x82, 0x85, 0x60, 0x53, 0x67, 0x78, 0x56, 0x38, 0x43, 0x44, 0x30, 0x63, + 0x26, 0x10, 0x77, 0x07, 0x31, 0x78, 0x42, 0x72, 0x14, 0x11, 0x16, 0x53, + 0x03, 0x85, 0x27, 0x68, 0x67, 0x46, 0x01, 0x50, 0x82, 0x37, 0x35, 0x32, + 0x07, 0x66, 0x10, 0x75, 0x04, 0x68, 0x12, 0x48, 0x06, 0x66, 0x03, 0x03, + 0x26, 0x52, 0x31, 0x24, 0x45, 0x40, 0x88, 0x00, 0x31, 0x80, 0x88, 0x76, + 0x72, 0x17, 0x30, 0x71, 0x82, 0x47, 0x21, 0x51, 0x27, 0x80, 0x11, 0x65, + 0x44, 0x74, 0x86, 0x61, 0x72, 0x23, 0x33, 0x80, 0x86, 0x60, 0x64, 0x46, + 0x83, 0x52, 0x15, 0x84, 0x20, 0x36, 0x80, 0x11, 0x80, 0x21, 0x18, 0x18, + 0x33, 0x17, 0x73, 0x54, 0x53, 0x48, 0x81, 0x00, 0x44, 0x86, 0x53, 0x67, + 0x43, 0x70, 0x57, 0x72, 0x58, 0x83, 0x34, 0x60, 0x38, 0x42, 0x32, 0x85, + 0x68, 0x10, 0x06, 0x04, 0x26, 0x04, 0x25, 0x84, 0x56, 0x02, 0x35, 0x68, + 0x20, 0x51, 0x83, 0x86, 0x38, 0x43, 0x24, 0x21, 0x22, 0x42, 0x45, 0x64, + 0x58, 0x58, 0x67, 0x71, 0x45, 0x72, 0x85, 0x04, 0x78, 0x87, 0x17, 0x18, + 0x06, 0x18, 0x83, 0x60, 0x86, 0x86, 0x41, 0x56, 0x50, 0x81, 0x16, 0x50, + 0x26, 0x46, 0x70, 0x06, 0x08, 0x26, 0x62, 0x27, 0x38, 0x31, 0x72, 0x40, + 0x72, 0x57, 0x30, 0x07, 0x27, 0x28, 0x86, 0x20, 0x66, 0x75, 0x88, 0x68, + 0x26, 0x07, 0x06, 0x40, 0x20, 0x33, 0x03, 0x43, 0x66, 0x31, 0x55, 0x46, + 0x42, 0x45, 0x34, 0x56, 0x67, 0x18, 0x73, 0x45, 0x65, 0x83, 0x70, 0x22, + 0x50, 0x84, 0x68, 0x56, 0x28, 0x80, 0x70, 0x36, 0x70, 0x84, 0x62, 0x37, + 0x17, 0x10, 0x06, 0x57, 0x17, 0x58, 0x47, 0x78, 0x70, 0x86, 0x55, 0x53, + 0x78, 0x22, 0x35, 0x14, 0x46, 0x77, 0x28, 0x56, 0x73, 0x03, 0x22, 0x87, + 0x00, 0x14, 0x33, 0x20, 0x61, 0x71, 0x58, 0x45, 0x52, 0x66, 0x32, 0x50, + 0x26, 0x51, 0x33, 0x47, 0x77, 0x38, 0x03, 0x55, 0x16, 0x43, 0x13, 0x47, + 0x35, 0x10, 0x66, 0x27, 0x51, 0x75, 0x74, 0x02, 0x46, 0x88, 0x81, 0x70, + 0x67, 0x43, 0x46, 0x81, 0x86, 0x01, 0x76, 0x52, 0x45, 0x33, 0x30, 0x87, + 0x21, 0x04, 0x34, 0x34, 0x01, 0x03, 0x22, 0x87, 0x63, 0x51, 0x55, 0x26, + 0x50, 0x81, 0x30, 0x77, 0x45, 0x44, 0x41, 0x68, 0x15, 0x41, 0x83, 0x63, + 0x64, 0x11, 0x20, 0x40, 0x26, 0x87, 0x30, 0x43, 0x67, 0x77, 0x12, 0x80, + 0x88, 0x46, 0x35, 0x54, 0x53, 0x00, 0x62, 0x45, 0x81, 0x04, 0x58, 0x36, + 0x51, 0x24, 0x84, 0x27, 0x80, 0x34, 0x51, 0x66, 0x63, 0x58, 0x43, 0x78, + 0x56, 0x01, 0x46, 0x51, 0x15, 0x74, 0x23, 0x21, 0x43, 0x66, 0x85, 0x22, + 0x47, 0x77, 0x31, 0x34, 0x50, 0x17, 0x83, 0x62, 0x42, 0x05, 0x50, 0x00, + 0x64, 0x84, 0x47, 0x12, 0x34, 0x40, 0x88, 0x00, 0x60, 0x47, 0x35, 0x40, + 0x57, 0x83, 0x33, 0x63, 0x08, 0x21, 0x06, 0x15, 0x22, 0x52, 0x07, 0x24, + 0x88, 0x51, 0x34, 0x86, 0x37, 0x06, 0x76, 0x22, 0x58, 0x85, 0x71, 0x26, + 0x56, 0x73, 0x47, 0x68, 0x16, 0x46, 0x46, 0x84, 0x25, 0x87, 0x08, 0x12, + 0x27, 0x05, 0x50, 0x08, 0x38, 0x32, 0x00, 0x23, 0x20, 0x80, 0x66, 0x34, + 0x53, 0x36, 0x00, 0x33, 0x46, 0x85, 0x72, 0x47, 0x06, 0x35, 0x54, 0x00, + 0x35, 0x77, 0x12, 0x27, 0x52, 0x30, 0x71, 0x42, 0x53, 0x68, 0x74, 0x37, + 0x45, 0x70, 0x05, 0x66, 0x43, 0x22, 0x44, 0x82, 0x85, 0x20, 0x72, 0x18, + 0x33, 0x30, 0x20, 0x53, 0x37, 0x33, 0x40, 0x77, 0x27, 0x80, 0x55, 0x25, + 0x30, 0x63, 0x52, 0x50, 0x40, 0x67, 0x33, 0x46, 0x13, 0x18, 0x07, 0x28, + 0x07, 0x17, 0x24, 0x83, 0x77, 0x63, 0x45, 0x73, 0x18, 0x58, 0x51, 0x60, + 0x23, 0x33, 0x44, 0x36, 0x25, 0x16, 0x43, 0x38, 0x16, 0x08, 0x58, 0x77, + 0x34, 0x62, 0x42, 0x88, 0x30, 0x07, 0x03, 0x65, 0x85, 0x37, 0x55, 0x00, + 0x75, 0x52, 0x31, 0x50, 0x37, 0x02, 0x13, 0x24, 0x63, 0x04, 0x37, 0x08, + 0x68, 0x06, 0x36, 0x15, 0x03, 0x03, 0x00, 0x43, 0x58, 0x63, 0x57, 0x08, + 0x02, 0x11, 0x06, 0x64, 0x73, 0x46, 0x35, 0x22, 0x62, 0x03, 0x30, 0x43, + 0x80, 0x21, 0x08, 0x52, 0x87, 0x57, 0x83, 0x21, 0x07, 0x88, 0x67, 0x48, + 0x08, 0x56, 0x34, 0x74, 0x36, 0x73, 0x42, 0x84, 0x05, 0x84, 0x66, 0x84, + 0x14, 0x37, 0x00, 0x55, 0x10, 0x87, 0x34, 0x26, 0x44, 0x77, 0x21, 0x12, + 0x73, 0x84, 0x73, 0x65, 0x26, 0x47, 0x25, 0x77, 0x14, 0x47, 0x04, 0x17, + 0x86, 0x44, 0x26, 0x02, 0x47, 0x11, 0x87, 0x40, 0x81, 0x22, 0x16, 0x60, + 0x58, 0x47, 0x17, 0x81, 0x37, 0x06, 0x76, 0x80, 0x81, 0x70, 0x58, 0x18, + 0x55, 0x85, 0x47, 0x13, 0x63, 0x42, 0x10, 0x75, 0x58, 0x01, 0x63, 0x58, + 0x35, 0x85, 0x18, 0x44, 0x03, 0x84, 0x71, 0x10, 0x33, 0x87, 0x42, 0x62, + 0x82, 0x47, 0x74, 0x13, 0x65, 0x54, 0x42, 0x70, 0x73, 0x46, 0x35, 0x77, + 0x75, 0x00, 0x66, 0x25, 0x62, 0x68, 0x42, 0x02, 0x12, 0x46, 0x83, 0x86, + 0x46, 0x16, 0x64, 0x60, 0x31, 0x22, 0x53, 0x88, 0x84, 0x54, 0x00, 0x84, + 0x57, 0x34, 0x46, 0x47, 0x54, 0x47, 0x25, 0x60, 0x54, 0x61, 0x66, 0x84, + 0x66, 0x30, 0x88, 0x06, 0x38, 0x27, 0x15, 0x63, 0x28, 0x71, 0x83, 0x84, + 0x06, 0x52, 0x24, 0x76, 0x81, 0x16, 0x06, 0x62, 0x13, 0x03, 0x30, 0x18, + 0x68, 0x02, 0x80, 0x13, 0x84, 0x63, 0x05, 0x05, 0x65, 0x72, 0x38, 0x75, + 0x83, 0x65, 0x72, 0x32, 0x30, 0x68, 0x80, 0x46, 0x12, 0x26, 0x06, 0x65, + 0x16, 0x75, 0x57, 0x05, 0x32, 0x41, 0x32, 0x27, 0x67, 0x35, 0x17, 0x08, + 0x01, 0x53, 0x00, 0x16, 0x28, 0x46, 0x01, 0x34, 0x88, 0x77, 0x01, 0x11, + 0x88, 0x15, 0x57, 0x13, 0x15, 0x46, 0x43, 0x11, 0x70, 0x47, 0x32, 0x88, + 0x28, 0x56, 0x36, 0x82, 0x34, 0x55, 0x50, 0x41, 0x86, 0x27, 0x65, 0x63, + 0x11, 0x11, 0x68, 0x75, 0x05, 0x10, 0x42, 0x54, 0x41, 0x44, 0x27, 0x85, + 0x22, 0x11, 0x17, 0x17, 0x88, 0x15, 0x36, 0x85, 0x15, 0x74, 0x47, 0x16, + 0x62, 0x55, 0x36, 0x55, 0x83, 0x63, 0x02, 0x50, 0x28, 0x55, 0x76, 0x87, + 0x53, 0x27, 0x13, 0x71, 0x03, 0x72, 0x37, 0x05, 0x71, 0x47, 0x61, 0x71, + 0x36, 0x51, 0x84, 0x12, 0x42, 0x36, 0x64, 0x44, 0x66, 0x41, 0x43, 0x52, + 0x05, 0x21, 0x08, 0x51, 0x57, 0x03, 0x33, 0x63, 0x86, 0x02, 0x58, 0x42, + 0x66, 0x28, 0x14, 0x81, 0x10, 0x54, 0x62, 0x68, 0x17, 0x30, 0x38, 0x75, + 0x64, 0x33, 0x21, 0x65, 0x88, 0x56, 0x86, 0x63, 0x63, 0x28, 0x13, 0x40, + 0x62, 0x54, 0x01, 0x20, 0x40, 0x88, 0x65, 0x47, 0x88, 0x61, 0x71, 0x65, + 0x76, 0x23, 0x72, 0x62, 0x34, 0x86, 0x70, 0x30, 0x11, 0x51, 0x15, 0x63, + 0x20, 0x50, 0x75, 0x35, 0x02, 0x12, 0x21, 0x08, 0x42, 0x65, 0x31, 0x43, + 0x55, 0x67, 0x11, 0x15, 0x25, 0x72, 0x01, 0x06, 0x85, 0x36, 0x30, 0x15, + 0x05, 0x57, 0x58, 0x60, 0x58, 0x78, 0x43, 0x14, 0x31, 0x32, 0x78, 0x78, + 0x80, 0x87, 0x38, 0x47, 0x88, 0x63, 0x78, 0x81, 0x81, 0x38, 0x73, 0x42, + 0x61, 0x78, 0x38, 0x85, 0x24, 0x66, 0x77, 0x33, 0x50, 0x60, 0x21, 0x15, + 0x14, 0x64, 0x23, 0x82, 0x32, 0x68, 0x01, 0x35, 0x44, 0x07, 0x83, 0x47, + 0x53, 0x85, 0x53, 0x57, 0x52, 0x83, 0x23, 0x35, 0x18, 0x76, 0x01, 0x15, + 0x21, 0x34, 0x32, 0x57, 0x73, 0x33, 0x36, 0x55, 0x18, 0x86, 0x15, 0x81, + 0x61, 0x68, 0x24, 0x18, 0x42, 0x21, 0x22, 0x30, 0x84, 0x14, 0x48, 0x15, + 0x12, 0x01, 0x10, 0x30, 0x24, 0x77, 0x72, 0x42, 0x54, 0x43, 0x66, 0x06, + 0x77, 0x17, 0x70, 0x76, 0x03, 0x01, 0x45, 0x25, 0x40, 0x35, 0x00, 0x18, + 0x38, 0x73, 0x23, 0x77, 0x35, 0x26, 0x50, 0x86, 0x35, 0x71, 0x13, 0x73, + 0x44, 0x81, 0x60, 0x52, 0x77, 0x45, 0x65, 0x53, 0x73, 0x00, 0x85, 0x83, + 0x77, 0x85, 0x03, 0x51, 0x21, 0x11, 0x54, 0x80, 0x62, 0x88, 0x50, 0x18, + 0x02, 0x68, 0x13, 0x86, 0x52, 0x05, 0x34, 0x68, 0x01, 0x32, 0x07, 0x24, + 0x18, 0x03, 0x21, 0x30, 0x05, 0x72, 0x38, 0x64, 0x07, 0x64, 0x27, 0x11, + 0x41, 0x01, 0x83, 0x85, 0x25, 0x51, 0x06, 0x32, 0x60, 0x71, 0x04, 0x86, + 0x51, 0x76, 0x83, 0x38, 0x28, 0x57, 0x27, 0x62, 0x35, 0x45, 0x18, 0x73, + 0x50, 0x83, 0x13, 0x28, 0x86, 0x37, 0x66, 0x61, 0x42, 0x63, 0x11, 0x67, + 0x50, 0x33, 0x11, 0x25, 0x53, 0x76, 0x41, 0x76, 0x03, 0x14, 0x33, 0x17, + 0x72, 0x12, 0x23, 0x44, 0x18, 0xA8, 0x2E, 0x4F, 0x5C, 0x9E, 0xA0, 0xFA, + 0xF9, 0x9E, 0xB0, 0x4D, 0x78, 0xA7, 0x33, 0x27, 0x11, 0x11, 0x7C, 0x33, + 0xF1, 0x8E, 0xCA, 0x21, 0xF8, 0x74, 0x33, 0x76, 0xAD, 0xA5, 0x21, 0x98, + 0x04, 0xA7, 0xED, 0x9A, 0x55, 0x57, 0xFC, 0xD6, 0x7A, 0x35, 0x50, 0xB3, + 0xA4, 0xB8, 0xC5, 0x88, 0x62, 0x9C, 0x02, 0x14, 0x75, 0xFA, 0x3D, 0x56, + 0xD5, 0xD6, 0xCF, 0xBB, 0x1A, 0x09, 0xBD, 0xA8, 0xD1, 0x4D, 0xE6, 0x22, + 0xDD, 0xFF, 0x16, 0xD8, 0xBC, 0x99, 0xB1, 0x42, 0x78, 0xA8, 0xAF, 0x1D, + 0x76, 0xBE, 0xD1, 0x57, 0x67, 0x2D, 0xD9, 0xC3, 0x23, 0x16, 0xF9, 0x7E, + 0x8D, 0xAA, 0xDE, 0xF8, 0xD9, 0xDA, 0x69, 0x58, 0x67, 0x25, 0x56, 0x7F, + 0xB9, 0x6B, 0x59, 0x99, 0x0D, 0x4B, 0xF0, 0xBC, 0x9C, 0x19, 0x5B, 0x90, + 0xB7, 0x42, 0x95, 0xF5, 0x67, 0x5B, 0x24, 0x25, 0x7C, 0x27, 0x10, 0xC1, + 0x75, 0xB0, 0x15, 0x3F, 0x29, 0x11, 0x32, 0x8C, 0x2E, 0xB7, 0xAB, 0xB9, + 0xAD, 0x46, 0xE7, 0x0A, 0x8B, 0x53, 0xC3, 0x9E, 0xA6, 0x42, 0xCE, 0xE4, + 0xB3, 0xCB, 0x42, 0x62, 0x0E, 0x86, 0x3C, 0xE8, 0xB6, 0x50, 0xCE, 0x8A, + 0xDC, 0xD9, 0x23, 0x72, 0x1A, 0x16, 0x87, 0x02, 0x3C, 0x67, 0x3A, 0x8C, + 0xBB, 0x6B, 0x03, 0xD5, 0x1C, 0xD1, 0x97, 0xE8, 0xC3, 0x46, 0xEB, 0xAD, + 0xCE, 0x93, 0x95, 0x0F, 0x88, 0xCE, 0xE2, 0x01, 0xDB, 0x9E, 0x32, 0x08, + 0x43, 0xE2, 0x9F, 0x30, 0x0D, 0x9A, 0x19, 0x50, 0x0D, 0x70, 0xA4, 0xCA, + 0xF2, 0x72, 0xC6, 0x9E, 0x4E, 0xEF, 0x69, 0xFB, 0xB8, 0xA5, 0x5E, 0xFD, + 0x7C, 0xA2, 0xBE, 0xD9, 0x90, 0xD2, 0xD3, 0xB5, 0x82, 0x84, 0x8F, 0x9C, + 0x45, 0xC2, 0xAB, 0xC5, 0x4C, 0xFC, 0x47, 0xD3, 0x4F, 0x06, 0xC0, 0xFF, + 0xA5, 0x6F, 0xCD, 0x76, 0x2A, 0xB9, 0xCB, 0xA9, 0x14, 0x6D, 0x77, 0x25, + 0x21, 0x89, 0x63, 0xB2, 0x40, 0xD7, 0x2B, 0x6D, 0x22, 0xC9, 0x31, 0x71, + 0xFB, 0xD4, 0x77, 0x88, 0xB7, 0x6E, 0x72, 0x04, 0x2D, 0xEF, 0x08, 0x78, + 0xD2, 0x3D, 0xF6, 0x31, 0xA1, 0xA1, 0xE5, 0xA6, 0x02, 0x76, 0x86, 0xDE, + 0x5B, 0x4A, 0x10, 0xE9, 0x10, 0x69, 0xC8, 0xF2, 0xBA, 0x02, 0x59, 0xB0, + 0x4D, 0x64, 0x09, 0xDA, 0x96, 0x56, 0x7C, 0xA5, 0x2D, 0xA4, 0x97, 0x02, + 0x6E, 0x58, 0x3A, 0x0E, 0xCE, 0xFC, 0x1F, 0x01, 0xE6, 0xB9, 0x88, 0xE2, + 0x1F, 0x97, 0x67, 0xA2, 0xB7, 0xE1, 0x67, 0x2D, 0xEB, 0x9A, 0x1E, 0x2A, + 0x3F, 0xCC, 0x86, 0x3A, 0xA9, 0x15, 0x17, 0xC3, 0x34, 0x62, 0x06, 0x01, + 0xB4, 0xFE, 0x79, 0x73, 0x0E, 0x93, 0x49, 0x35, 0xF4, 0xB6, 0xFB, 0xC4, + 0xE3, 0x26, 0x95, 0x14, 0x5C, 0x2B, 0x5F, 0x6A, 0x12, 0x7F, 0xEC, 0xC0, + 0xA2, 0x77, 0x45, 0x1E, 0xBC, 0x3F, 0xD5, 0x23, 0x44, 0x4F, 0x9E, 0xE7, + 0xC9, 0xC3, 0x45, 0x34, 0xF3, 0x56, 0xDB, 0x54, 0x4F, 0xC3, 0x1C, 0x1B, + 0xFD, 0xE5, 0xF6, 0x5C, 0x77, 0xEA, 0x2F, 0x7C, 0x2E, 0xAE, 0x4C, 0x55, + 0xEB, 0xAF, 0x10, 0x42, 0x71, 0xC5, 0x66, 0xFD, 0x4E, 0xBA, 0xC7, 0x1C, + 0x7A, 0x62, 0xC7, 0x49, 0x52, 0x81, 0x7A, 0xE6, 0x75, 0x50, 0x4D, 0x95, + 0x99, 0xB1, 0xB7, 0x62, 0xB6, 0xAC, 0xA1, 0x68, 0xA8, 0x32, 0x48, 0xC9, + 0xD9, 0xAD, 0xB0, 0xCE, 0xB1, 0x55, 0x6E, 0x57, 0x59, 0x49, 0x0B, 0xBC, + 0x0C, 0x79, 0x00, 0x79, 0x5A, 0xD7, 0x21, 0x23, 0x03, 0x8B, 0x66, 0x2F, + 0x64, 0xF1, 0x06, 0xA9, 0x99, 0x36, 0x81, 0xA2, 0x5D, 0x59, 0xAF, 0x7B, + 0xC9, 0x7A, 0x23, 0x5B, 0xE9, 0x28, 0x4C, 0x5B, 0xC4, 0x5A, 0x6C, 0x90, + 0xCB, 0x1C, 0x29, 0x99, 0xC6, 0x63, 0xD9, 0x6B, 0x47, 0x8E, 0x23, 0x07, + 0xF8, 0x55, 0x48, 0x95, 0x7D, 0x65, 0x74, 0x0E, 0x26, 0x73, 0xE9, 0xEB, + 0xD1, 0x35, 0x28, 0x29, 0x03, 0x8F, 0x46, 0x2B, 0x8F, 0xD3, 0xB5, 0x68, + 0x1D, 0xA5, 0x5C, 0x02, 0x52, 0x52, 0x38, 0x53, 0x52, 0x5E, 0xA0, 0xAD, + 0x64, 0x7E, 0x71, 0xAC, 0x2C, 0x5A, 0x88, 0x93, 0xE6, 0x03, 0xAC, 0x97, + 0xE5, 0x6C, 0x04, 0xCE, 0xB2, 0xF2, 0x6F, 0x5C, 0x5B, 0x4B, 0x6D, 0x94, + 0xAB, 0x81, 0x13, 0x80, 0xFD, 0x00, 0xF2, 0x20, 0x8F, 0xE8, 0x65, 0x35, + 0x08, 0x6A, 0xEB, 0xFD, 0x35, 0xC2, 0x91, 0x20, 0x62, 0x4C, 0x04, 0xFB, + 0xB6, 0x11, 0x39, 0x29, 0xD9, 0xC5, 0x56, 0x35, 0x02, 0x53, 0x76, 0x6C, + 0x20, 0x9F, 0xDB, 0xA8, 0x3C, 0x95, 0xFC, 0xCD, 0x34, 0x2A, 0x28, 0x09, + 0x93, 0x55, 0xD0, 0x0B, 0xC8, 0x63, 0xF4, 0xEE, 0xF5, 0x96, 0xEB, 0x0B, + 0x42, 0xEB, 0xCC, 0x7C, 0x79, 0x49, 0x1C, 0xCE, 0xAE, 0x20, 0x5E, 0xA0, + 0xB8, 0x05, 0x9F, 0xBB, 0x8A, 0x57, 0x26, 0xC5, 0x94, 0x9D, 0x2B, 0x15, + 0xE7, 0xE2, 0x9C, 0x51, 0xFC, 0x9B, 0x02, 0xEE, 0x1A, 0x4F, 0xC3, 0x57, + 0xB5, 0xF1, 0xBE, 0xF9, 0xC4, 0xAD, 0xD4, 0x6A, 0x2A, 0x92, 0x0C, 0x2F, + 0xBF, 0x08, 0xA3, 0x7E, 0xB1, 0x51, 0x4B, 0xFA, 0x15, 0x11, 0x0A, 0x43, + 0x92, 0xA7, 0x4C, 0x6F, 0x13, 0xC5, 0x0C, 0x5C, 0xFF, 0xD9, 0x75, 0x31, + 0x09, 0x8D, 0x7C, 0xD2, 0x3B, 0x60, 0xEB, 0x35, 0xC4, 0xA4, 0x28, 0xB4, + 0x6C, 0x55, 0x38, 0x6E, 0x10, 0x10, 0xC4, 0xBA, 0x7F, 0x70, 0xE4, 0xC7, + 0xEC, 0xB7, 0x57, 0x5F, 0x30, 0x63, 0xA7, 0x1E, 0x84, 0xDF, 0xDC, 0xF0, + 0x9A, 0x58, 0xB2, 0xCD, 0xB0, 0xF9, 0x9F, 0x27, 0xED, 0x37, 0x86, 0x10, + 0xD2, 0x5C, 0xBA, 0xD7, 0xBF, 0xA6, 0xBA, 0x0D, 0x59, 0x18, 0x9C, 0xFE, + 0x88, 0xEA, 0xB9, 0xB4, 0x6D, 0x7E, 0x6D, 0xB0, 0x30, 0x7E, 0xAB, 0xE4, + 0x19, 0x8E, 0x99, 0xBD, 0x71, 0xF7, 0x79, 0xAB, 0x66, 0x58, 0x1E, 0x09, + 0x12, 0xFC, 0x7B, 0x1D, 0x25, 0x85, 0x24, 0x5E, 0x9A, 0x12, 0x68, 0x7A, + 0x97, 0x5C, 0xD5, 0xE8, 0xE1, 0xDC, 0xC0, 0x45, 0xD5, 0xF8, 0x91, 0xC4, + 0xC6, 0x85, 0xDB, 0x07, 0xCF, 0x81, 0xE7, 0x73, 0x89, 0xB3, 0x63, 0xEB, + 0x6B, 0xDF, 0xE3, 0x9B, 0x27, 0xFF, 0x84, 0xC9, 0x7E, 0xEF, 0xEE, 0x16, + 0x2E, 0x3B, 0x45, 0x1F, 0xE6, 0x91, 0x47, 0x19, 0xCB, 0x64, 0x36, 0xD8, + 0x55, 0x96, 0x0F, 0xF9, 0x15, 0xD7, 0xCE, 0xA6, 0xAD, 0xEA, 0xFD, 0xFC, + 0x1C, 0x05, 0x78, 0x6C, 0x49, 0xF9, 0x23, 0xA4, 0x74, 0xFF, 0xDF, 0xC3, + 0x15, 0x3A, 0x06, 0xE6, 0xED, 0x0B, 0x0A, 0xD2, 0x20, 0xD7, 0x25, 0x24, + 0x43, 0x4D, 0x52, 0x73, 0xC0, 0xAA, 0xB6, 0xDD, 0xE4, 0xE9, 0x14, 0x76, + 0xD5, 0x81, 0xA2, 0x69, 0x5A, 0x60, 0xDE, 0x6D, 0x9F, 0x44, 0xD7, 0x7A, + 0xA0, 0x82, 0x66, 0xE9, 0x38, 0xEE, 0xB4, 0xA9, 0x59, 0x7C, 0x9B, 0x64, + 0x98, 0x60, 0x59, 0xE4, 0x92, 0x62, 0xA4, 0xEA, 0xB2, 0x45, 0x4E, 0x14, + 0x01, 0x5A, 0xD0, 0x53, 0x6C, 0x42, 0x73, 0x3A, 0x5D, 0x77, 0xD7, 0x99, + 0x5C, 0x2A, 0x20, 0x44, 0x60, 0x09, 0xEB, 0xFE, 0x56, 0x32, 0xC8, 0x0C, + 0x08, 0xED, 0x2B, 0x97, 0xAF, 0x35, 0x06, 0x64, 0x89, 0xF5, 0x97, 0xEB, + 0x1B, 0x1F, 0x11, 0xF0, 0x4F, 0x60, 0xE0, 0xC9, 0x04, 0x01, 0x59, 0xC4, + 0x4A, 0xB3, 0xE6, 0x0E, 0x0A, 0x15, 0x22, 0x9D, 0x19, 0x12, 0x28, 0xBE, + 0xD1, 0x7B, 0xBC, 0x3A, 0xC9, 0x39, 0xB3, 0xC6, 0x7C, 0xEE, 0x13, 0x5F, + 0x35, 0x2C, 0x27, 0x21, 0x6C, 0x9C, 0x31, 0xF7, 0x2A, 0x3E, 0x87, 0x04, + 0x0C, 0x5F, 0x61, 0x93, 0x06, 0xEB, 0x0B, 0x6C, 0xCA, 0x2A, 0x9C, 0xE7, + 0xB2, 0x2A, 0x16, 0x94, 0xD0, 0x0C, 0xA9, 0xC0, 0x5E, 0x31, 0x51, 0x26, + 0x45, 0x7F, 0x26, 0xCE, 0x84, 0xF9, 0x61, 0x72, 0x41, 0x86, 0x07, 0x82, + 0xF8, 0x64, 0xB4, 0x73, 0xD8, 0x40, 0x17, 0x49, 0x19, 0x02, 0xB1, 0xBD, + 0xC8, 0xCD, 0xC5, 0x80, 0x0D, 0xD4, 0x61, 0x27, 0xFB, 0x80, 0xA7, 0x1C, + 0x09, 0x5B, 0x47, 0x3A, 0x56, 0x25, 0x29, 0xB3, 0xB1, 0xE7, 0xE4, 0x37, + 0xE1, 0x58, 0xA5, 0xF6, 0x66, 0x6E, 0x99, 0x74, 0xD0, 0x05, 0xB0, 0x62, + 0xC2, 0x30, 0x9E, 0x6D, 0xCE, 0x98, 0xF9, 0xB6, 0x58, 0xC6, 0xE3, 0xF9, + 0xA2, 0x16, 0xD5, 0x8C, 0x8C, 0x91, 0x42, 0xBD, 0x1C, 0x8C, 0x85, 0xA9, + 0xDA, 0x87, 0x2E, 0xBB, 0xFA, 0xD3, 0xFE, 0xA9, 0xD9, 0xAB, 0xA2, 0xB6, + 0x8C, 0x0E, 0x8F, 0x19, 0xC6, 0xFF, 0x5F, 0x00, 0x58, 0x4D, 0x45, 0xDA, + 0xF9, 0xD6, 0xC9, 0xD6, 0x9E, 0xD0, 0x4B, 0x8D, 0xA8, 0xD6, 0x87, 0x25, + 0x8B, 0x77, 0x80, 0x79, 0x27, 0x61, 0x2C, 0x53, 0x04, 0x46, 0xFE, 0xA7, + 0x69, 0x7A, 0xE3, 0xF9, 0x26, 0x69, 0x89, 0x29, 0xBC, 0x6A, 0x5A, 0x8C, + 0xF3, 0xE2, 0x02, 0x4C, 0x0F, 0x0C, 0x5E, 0xE5, 0x7B, 0x58, 0x69, 0xBF, + 0x98, 0x18, 0x81, 0xCA, 0xF9, 0xE3, 0x66, 0x5F, 0xC7, 0xF7, 0xEF, 0xC6, + 0x78, 0x92, 0x9F, 0x87, 0xA5, 0x6E, 0xAA, 0x42, 0xEA, 0x4D, 0x1F, 0xF6, + 0x69, 0x18, 0x22, 0xDD, 0x79, 0xA4, 0x70, 0x96, 0xB7, 0x76, 0xD1, 0xD8, + 0xF0, 0x14, 0x56, 0xE5, 0x87, 0x3B, 0x07, 0x38, 0x40, 0x6C, 0x38, 0x2C, + 0x57, 0x3A, 0xE9, 0xCD, 0xE2, 0xD9, 0xE7, 0xF2, 0x31, 0xB6, 0xCC, 0x5C, + 0x67, 0x6E, 0x7C, 0xF4, 0x39, 0x63, 0x37, 0x30, 0x13, 0xA5, 0x80, 0x75, + 0x38, 0x1F, 0xF0, 0x94, 0x9B, 0xE0, 0x84, 0x54, 0x6D, 0x72, 0xE4, 0xF8, + 0xA3, 0xE5, 0xFE, 0x4A, 0xA5, 0x09, 0x1A, 0xDD, 0x23, 0x4E, 0x2A, 0xFE, + 0x00, 0x30, 0xB1, 0xB6, 0x63, 0xAE, 0x9D, 0x2D, 0x32, 0x41, 0x09, 0x86, + 0xB9, 0x40, 0x2A, 0xAA, 0xF2, 0x46, 0x5B, 0x74, 0xA5, 0xE2, 0xD0, 0xBC, + 0x38, 0xE3, 0xA9, 0x2B, 0xBD, 0xDD, 0x8A, 0x1F, 0xED, 0x7B, 0x94, 0x8C, + 0x23, 0xCC, 0xE6, 0xF8, 0xC0, 0x8F, 0xE3, 0x56, 0x83, 0x5B, 0xA6, 0x5B, + 0x0F, 0x98, 0x40, 0x68, 0x61, 0x6E, 0xF4, 0x81, 0x38, 0xEF, 0xD8, 0x9B, + 0xF3, 0x57, 0xA5, 0x4D, 0x2E, 0xBB, 0xF3, 0x76, 0xCB, 0xDC, 0xC6, 0x9C, + 0x5F, 0x1F, 0x61, 0xC6, 0x4D, 0x27, 0x94, 0xBC, 0x06, 0xCC, 0xB9, 0xAB, + 0xDF, 0x66, 0xE2, 0x50, 0x85, 0xD8, 0xC8, 0x30, 0xE2, 0xAE, 0x3B, 0x0F, + 0xE0, 0xF0, 0x7A, 0x7A, 0xF8, 0xB9, 0x32, 0x0B, 0xF3, 0x42, 0x97, 0x09, + 0x97, 0xD6, 0x7D, 0x7C, 0x12, 0x59, 0x3A, 0x8F, 0xBF, 0xAD, 0xE6, 0x35, + 0xAA, 0xC5, 0x30, 0x83, 0xA7, 0x02, 0x2C, 0x47, 0xD5, 0xF7, 0x7A, 0x52, + 0xB5, 0x7B, 0x59, 0x8D, 0xA9, 0x39, 0x2A, 0xE6, 0xD8, 0x6A, 0xFC, 0x46, + 0xFC, 0x06, 0x45, 0x51, 0x81, 0xB9, 0xC7, 0x5A, 0x64, 0x6D, 0xC2, 0x1F, + 0x81, 0xE4, 0xBF, 0x21, 0x37, 0x53, 0xDE, 0x73, 0x7F, 0xD2, 0xA1, 0x40, + 0x02, 0x79, 0x20, 0xAD, 0xD3, 0x5A, 0x22, 0x3F, 0x9F, 0x5F, 0x44, 0x65, + 0xCE, 0xB6, 0x0C, 0x03, 0xED, 0x04, 0x55, 0xA3, 0x33, 0xA5, 0xCC, 0x83, + 0xAD, 0xBF, 0x43, 0xF1, 0xF4, 0x2C, 0x2C, 0xCB, 0x83, 0x28, 0xC2, 0x1C, + 0x7A, 0xB7, 0xFA, 0xED, 0x2B, 0x21, 0xCF, 0xAD, 0xE2, 0xDA, 0x55, 0x22, + 0x3A, 0xAA, 0xB2, 0xAF, 0x9B, 0x41, 0xC7, 0x33, 0x23, 0x41, 0x74, 0x63, + 0x41, 0xB3, 0x9A, 0xA2, 0xF4, 0x38, 0x15, 0x65, 0x0F, 0x54, 0x80, 0x51, + 0x14, 0x24, 0xCF, 0xA6, 0x90, 0x17, 0x79, 0xC4, 0xD1, 0x8B, 0x63, 0x8C, + 0xC0, 0x28, 0x7A, 0xAA, 0xF3, 0x16, 0x80, 0x33, 0x8D, 0x20, 0xB1, 0x7C, + 0x74, 0x49, 0xFD, 0xC6, 0xA2, 0x78, 0xA8, 0xD9, 0x6A, 0x82, 0xEE, 0x4C, + 0x4E, 0xCA, 0x40, 0x12, 0x5E, 0x2D, 0x65, 0x29, 0x00, 0x71, 0xC7, 0xAE, + 0xF1, 0xBE, 0x6A, 0x99, 0x15, 0x98, 0xFB, 0x9D, 0x59, 0x51, 0x25, 0x23, + 0xBC, 0xD4, 0xB3, 0x8C, 0x56, 0x6B, 0x8E, 0x80, 0xA7, 0x3A, 0xE3, 0x33, + 0xE1, 0x34, 0x41, 0x43, 0x27, 0xEF, 0x1D, 0x83, 0xC4, 0x7C, 0x49, 0xDF, + 0xE7, 0x93, 0x6D, 0xF1, 0x33, 0x8A, 0x5E, 0x24, 0x77, 0x87, 0x86, 0x8F, + 0xC8, 0x4F, 0xDC, 0xB9, 0x5A, 0xC8, 0x9C, 0x18, 0x5C, 0x4B, 0xB5, 0xFD, + 0x57, 0xB2, 0x33, 0x8A, 0xC4, 0x2B, 0x41, 0xC1, 0x0A, 0x82, 0x3D, 0xF3, + 0x96, 0x24, 0xF3, 0x6B, 0x15, 0xA2, 0xF0, 0x67, 0x58, 0x4E, 0x06, 0xCA, + 0x2E, 0x08, 0xCC, 0xAF, 0xF1, 0x61, 0x8F, 0xE0, 0x1D, 0xD0, 0x6D, 0xF3, + 0x51, 0x2E, 0x0B, 0x72, 0x4D, 0xEC, 0x85, 0x06, 0xDA, 0x24, 0x21, 0x5A, + 0xCA, 0xCC, 0x2C, 0x51, 0xB8, 0x2A, 0xD8, 0xD3, 0x02, 0x00, 0x2F, 0xB4, + 0x10, 0x68, 0xB1, 0xDA, 0x4F, 0x8B, 0xB1, 0x47, 0x98, 0x7B, 0x35, 0x16, + 0xBA, 0xD5, 0xDB, 0xDD, 0xF0, 0x13, 0x18, 0xFD, 0x3F, 0xA9, 0xBC, 0x43, + 0x70, 0x2A, 0xC4, 0x98, 0xC7, 0x19, 0xD9, 0x5F, 0x2E, 0x84, 0x1B, 0x62, + 0x2A, 0x5E, 0x48, 0x48, 0xA3, 0xC5, 0xC2, 0x62, 0x95, 0x99, 0x92, 0xEA, + 0x7A, 0x7D, 0x72, 0xCA, 0x8A, 0x36, 0x80, 0x28, 0xF4, 0x97, 0xDF, 0xAD, + 0x93, 0x35, 0x5C, 0xBB, 0x1B, 0xB9, 0x78, 0x6D, 0x14, 0xFF, 0x2C, 0xF5, + 0x90, 0x31, 0x78, 0x48, 0xF9, 0x58, 0x56, 0x42, 0x71, 0x10, 0xDD, 0xA3, + 0x6F, 0x51, 0x92, 0xA8, 0x16, 0xCE, 0x9C, 0x88, 0x16, 0xCC, 0x7B, 0xBF, + 0xC8, 0x04, 0xEF, 0xC4, 0x00, 0x85, 0xA3, 0x85, 0x0B, 0x89, 0xF1, 0xE7, + 0xFE, 0x56, 0x56, 0xDB, 0xA4, 0x10, 0xF9, 0x06, 0xA9, 0x7C, 0x32, 0x33, + 0x6C, 0x1A, 0xE7, 0xE8, 0x17, 0x37, 0xA8, 0x3E, 0x08, 0x73, 0x54, 0xE4, + 0x28, 0xDA, 0x85, 0x38, 0xD9, 0x48, 0xDB, 0xF5, 0xDF, 0xAC, 0xB5, 0x9D, + 0xD2, 0xB5, 0xFD, 0x3B, 0xC8, 0x03, 0xF4, 0xBA, 0x43, 0x2C, 0x9A, 0x73, + 0x9D, 0xF2, 0xCF, 0xA9, 0xED, 0x94, 0x84, 0x32, 0x0F, 0x97, 0xED, 0xFF, + 0x1A, 0x48, 0xC6, 0xB8, 0x6B, 0x30, 0x02, 0xCF, 0xB7, 0x72, 0xDD, 0x5E, + 0x56, 0x2B, 0xC4, 0xC3, 0xD6, 0x83, 0xED, 0x96, 0x4B, 0x61, 0x99, 0xFA, + 0x05, 0x14, 0xB0, 0x79, 0x0D, 0x95, 0x80, 0x95, 0xB7, 0xB8, 0x5C, 0x6B, + 0xE8, 0x75, 0xFB, 0xB5, 0x59, 0xE1, 0x93, 0x01, 0x46, 0xCC, 0xEA, 0x63, + 0xA3, 0x88, 0xA1, 0x94, 0xFE, 0x09, 0xC3, 0xDE, 0xA0, 0x3B, 0xE5, 0x2D, + 0xE2, 0x7E, 0x90, 0x10, 0x17, 0xAF, 0xE8, 0x09, 0xAF, 0x63, 0x0A, 0x73, + 0x82, 0xBF, 0x5C, 0x4C, 0xD4, 0xD1, 0xB8, 0xF4, 0x15, 0x79, 0xFB, 0x43, + 0x48, 0xED, 0xE4, 0xCA, 0x05, 0xF4, 0xCD, 0x3F, 0x13, 0x9A, 0x31, 0xB2, + 0x54, 0x4E, 0x51, 0x6D, 0xBE, 0x40, 0x86, 0xB9, 0xBB, 0x4B, 0x2B, 0xED, + 0x47, 0xE2, 0xD2, 0x30, 0x98, 0x2D, 0xD5, 0x19, 0x24, 0x29, 0xD3, 0x77, + 0xB7, 0xC0, 0x74, 0x5C, 0xC0, 0x68, 0xE2, 0xF5, 0xA4, 0xAA, 0x04, 0xC7, + 0xFF, 0x87, 0x20, 0x9E, 0xD1, 0x25, 0x99, 0x76, 0xA0, 0xFC, 0x9B, 0x25, + 0xE9, 0xE8, 0x51, 0xD4, 0xE3, 0x50, 0x2C, 0x02, 0xC8, 0x5D, 0x6D, 0xFF, + 0x02, 0x9E, 0x21, 0x1D, 0x01, 0xEB, 0xF0, 0xE9, 0xE7, 0x18, 0x8D, 0x56, + 0x8F, 0x84, 0x37, 0xD8, 0x13, 0xB0, 0xF1, 0x22, 0xF2, 0xFB, 0x17, 0x60, + 0x3B, 0x69, 0x3E, 0xD9, 0xC3, 0x8F, 0x17, 0xCF, 0xD5, 0x0B, 0x81, 0x5E, + 0x6D, 0x9D, 0xFC, 0x0E, 0xD2, 0xCC, 0xF1, 0x9F, 0x63, 0x99, 0x27, 0x4A, + 0x14, 0x20, 0xF2, 0x35, 0xA5, 0x9D, 0x8B, 0xF7, 0x24, 0x34, 0x5E, 0x14, + 0xE4, 0x5D, 0x9E, 0x4B, 0xE8, 0x93, 0x4D, 0xFC, 0x3F, 0xA9, 0x26, 0x78, + 0xDB, 0x61, 0xD7, 0x11, 0x8B, 0xF5, 0x3C, 0xB8, 0xA2, 0x22, 0x5B, 0x33, + 0x5F, 0x7E, 0xAE, 0x50, 0xE3, 0xF9, 0x41, 0x23, 0x76, 0x28, 0xDB, 0x76, + 0xD8, 0xEA, 0x38, 0xF7, 0x7A, 0x72, 0xAF, 0x3A, 0x26, 0xC8, 0x1F, 0xE4, + 0x35, 0x23, 0xB3, 0x35, 0x53, 0x5A, 0x5D, 0x1D, 0xB7, 0xC3, 0x8F, 0x34, + 0x10, 0x82, 0xBB, 0x57, 0x34, 0xD0, 0x89, 0xE8, 0xAE, 0x30, 0x9C, 0xFD, + 0xA3, 0xA0, 0xBC, 0xB5, 0xCD, 0x5B, 0x09, 0x71, 0x13, 0xC8, 0xED, 0xF9, + 0x61, 0x6A, 0xA4, 0xF6, 0xE6, 0x63, 0x1B, 0x91, 0x25, 0x27, 0x6F, 0xB3, + 0xF6, 0x80, 0xA3, 0x43, 0x41, 0xC3, 0xDB, 0x66, 0x8D, 0xC6, 0xCA, 0xD4, + 0x5F, 0xC9, 0x3B, 0x27, 0x08, 0xCA, 0x2A, 0xF7, 0x5C, 0xCC, 0xE7, 0x34, + 0xFD, 0x19, 0x1C, 0x50, 0x08, 0x9D, 0xAD, 0x53, 0x98, 0x2F, 0xDD, 0xAE, + 0x02, 0x53, 0x1F, 0xF9, 0x3E, 0x1F, 0x21, 0xFF, 0x39, 0x5F, 0xC0, 0xA1, + 0x28, 0x74, 0xED, 0xF0, 0x6B, 0x6F, 0x96, 0x47, 0xE9, 0x5A, 0x73, 0x24, + 0x58, 0x6C, 0x71, 0xDF, 0xD9, 0x1D, 0x90, 0x1D, 0x62, 0x18, 0x58, 0x19, + 0x0F, 0xEC, 0xD0, 0x0C, 0xCD, 0x11, 0x0B, 0xBA, 0xC5, 0x9F, 0x96, 0xCB, + 0x88, 0x4C, 0x3C, 0x93, 0x99, 0x47, 0x48, 0xA5, 0x6F, 0x41, 0x28, 0x3B, + 0xFC, 0x41, 0xFB, 0x89, 0x05, 0x21, 0x53, 0xA8, 0x94, 0x58, 0x8C, 0x3C, + 0xB9, 0x01, 0x7F, 0x3D, 0x66, 0x32, 0x6C, 0x98, 0x56, 0x37, 0xE5, 0x75, + 0xAC, 0xB8, 0x12, 0x34, 0x63, 0x42, 0x65, 0x40, 0x25, 0xD6, 0x02, 0xDE, + 0x3B, 0xA9, 0x40, 0xC1, 0x9A, 0xC1, 0xA6, 0x33, 0xDF, 0xFD, 0xA9, 0x77, + 0xB5, 0x29, 0xB8, 0x01, 0x3E, 0x19, 0xC1, 0xD6, 0xD0, 0x68, 0x0F, 0x4D, + 0xAE, 0x62, 0xC9, 0x24, 0x45, 0x0A, 0xE6, 0x6A, 0xAB, 0x82, 0xF2, 0x14, + 0x73, 0x06, 0x1D, 0xAB, 0x3D, 0x62, 0xB2, 0x47, 0xF9, 0x07, 0xE3, 0x55, + 0x19, 0x39, 0xAD, 0x3F, 0x54, 0x65, 0xE9, 0xD0, 0x8A, 0x82, 0xBF, 0xEA, + 0x17, 0xEE, 0xA1, 0xB6, 0xB2, 0xB9, 0x23, 0x75, 0x74, 0x77, 0xF9, 0x93, + 0x00, 0x0B, 0x2F, 0x43, 0xB7, 0x0F, 0x28, 0xAA, 0xAB, 0x1F, 0xE9, 0xA2, + 0x6A, 0xD1, 0xFD, 0x33, 0x61, 0x61, 0x6C, 0x0B, 0x0E, 0x24, 0x2F, 0xE7, + 0x66, 0x04, 0xB7, 0x03, 0x3A, 0x1F, 0x30, 0xE9, 0x7E, 0x28, 0xF5, 0x26, + 0xCA, 0x3C, 0x88, 0x0F, 0xE2, 0xB8, 0xD9, 0xD1, 0xB0, 0xC9, 0xFF, 0x18, + 0x8B, 0x31, 0xCB, 0x9D, 0x97, 0x42, 0x5A, 0xCA, 0xB9, 0xB2, 0x16, 0xD9, + 0x8A, 0x6A, 0xE3, 0x55, 0xE5, 0x83, 0xDA, 0x71, 0xE8, 0x86, 0x4E, 0xE3, + 0xD1, 0x6B, 0x07, 0x59, 0x79, 0x61, 0x90, 0xEF, 0x54, 0x5C, 0x1E, 0x62, + 0xBF, 0xEF, 0x92, 0xAF, 0x6C, 0xA1, 0x47, 0xB1, 0x32, 0x44, 0xD6, 0xC8, + 0x92, 0xFC, 0x8E, 0xF2, 0x23, 0xAB, 0x3F, 0x43, 0xF9, 0x24, 0xC2, 0xF4, + 0x66, 0x09, 0x7E, 0xE8}; static bssl::UniquePtr LoadExampleRSAKey() { bssl::UniquePtr rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER, diff --git a/crypto/evp_extra/p_dh_asn1.c b/crypto/evp_extra/p_dh_asn1.c index fc8cb1109a..973517e3ce 100644 --- a/crypto/evp_extra/p_dh_asn1.c +++ b/crypto/evp_extra/p_dh_asn1.c @@ -37,7 +37,7 @@ static int dh_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int dh_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int dh_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // RFC 2786 BIGNUM *pubkey = NULL; DH *dh = NULL; diff --git a/crypto/evp_extra/p_dsa_asn1.c b/crypto/evp_extra/p_dsa_asn1.c index 470d3bd04e..232bfbfa48 100644 --- a/crypto/evp_extra/p_dsa_asn1.c +++ b/crypto/evp_extra/p_dsa_asn1.c @@ -66,7 +66,7 @@ #include "internal.h" -static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int dsa_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // See RFC 3279, section 2.3.2. // Parameters may or may not be present. @@ -127,7 +127,7 @@ static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int dsa_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { // See PKCS#11, v2.40, section 2.5. if(pubkey) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); diff --git a/crypto/evp_extra/p_ec_asn1.c b/crypto/evp_extra/p_ec_asn1.c index de364a6f4f..34e636fa35 100644 --- a/crypto/evp_extra/p_ec_asn1.c +++ b/crypto/evp_extra/p_ec_asn1.c @@ -90,7 +90,7 @@ static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int eckey_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // See RFC 5480, section 2. // The parameters are a named curve. @@ -139,7 +139,7 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { } } -static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int eckey_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { // See RFC 5915. if(pubkey) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); diff --git a/crypto/evp_extra/p_ed25519_asn1.c b/crypto/evp_extra/p_ed25519_asn1.c index 488c64452b..693d2e8578 100644 --- a/crypto/evp_extra/p_ed25519_asn1.c +++ b/crypto/evp_extra/p_ed25519_asn1.c @@ -126,7 +126,7 @@ static int ed25519_get_pub_raw(const EVP_PKEY *pkey, uint8_t *out, return 1; } -static int ed25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int ed25519_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // See RFC 8410, section 4. // The parameters must be omitted. Public keys have length 32. @@ -166,7 +166,7 @@ static int ed25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { b_key->key + ED25519_PUBLIC_KEY_OFFSET, ED25519_PUBLIC_KEY_LEN) == 0; } -static int ed25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int ed25519_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { // See RFC 8410, section 7. // Parameters must be empty. The key is a 32-byte value wrapped in an extra diff --git a/crypto/evp_extra/p_pqdsa_asn1.c b/crypto/evp_extra/p_pqdsa_asn1.c index 539f9e5526..bd81826c70 100644 --- a/crypto/evp_extra/p_pqdsa_asn1.c +++ b/crypto/evp_extra/p_pqdsa_asn1.c @@ -20,6 +20,9 @@ static void pqdsa_free(EVP_PKEY *pkey) { static int pqdsa_get_priv_raw(const EVP_PKEY *pkey, uint8_t *out, size_t *out_len) { + GUARD_PTR(pkey); + GUARD_PTR(out_len); + if (pkey->pkey.pqdsa_key == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); return 0; @@ -88,16 +91,15 @@ static int pqdsa_get_pub_raw(const EVP_PKEY *pkey, uint8_t *out, return 1; } -static int pqdsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int pqdsa_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // See https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/ - // section 4. the only parameter that can be included is the OID which has - // length 9 - if (CBS_len(params) != 9) { + // section 4. There should be no parameters + if (CBS_len(params) > 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } // Set the pqdsa params on |out|. - if (!EVP_PKEY_pqdsa_set_params(out, OBJ_cbs2nid(params))) { + if (!EVP_PKEY_pqdsa_set_params(out, OBJ_cbs2nid(oid))) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } @@ -138,64 +140,80 @@ static int pqdsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { a->pkey.pqdsa_key->pqdsa->public_key_len) == 0; } -static int pqdsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int pqdsa_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { // See https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/ - // section 6. the only parameter that can be included is the OID which has - // length 9. - if (CBS_len(params) != 9) { + // section 6. There should be no parameters. + if (CBS_len(params) > 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } // Set the pqdsa params on |out|. - if (!EVP_PKEY_pqdsa_set_params(out, OBJ_cbs2nid(params))) { + if (!EVP_PKEY_pqdsa_set_params(out, OBJ_cbs2nid(oid))) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } - // check the size of the provided input against the private key and seed len - if (CBS_len(key) != out->pkey.pqdsa_key->pqdsa->private_key_len && - CBS_len(key) != out->pkey.pqdsa_key->pqdsa->keygen_seed_len) { - OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); - return 0; - } + // Try to parse as one of the three ASN.1 formats defined in ML-DSA-XX-PrivateKey + // Currently only the following cases are supported: + // Case 1: seed [0] OCTET STRING + // Case 2: expandedKey OCTET STRING - // See https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/ - // The caller can either provide the full key of size |private_key_len| or - // |keygen_seed_len|. - if (CBS_len(key) == out->pkey.pqdsa_key->pqdsa->private_key_len) { + // Once https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/ + // is stable we will implement: + // Case 3: both SEQUENCE { seed, expandedKey } - // Set the private key - if (!PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key, key)) { - // PQDSA_KEY_set_raw_private_key sets the appropriate error. + if (CBS_peek_asn1_tag(key, CBS_ASN1_CONTEXT_SPECIFIC | 0)) { + // Case 1: seed [0] OCTET STRING + CBS seed; + if (!CBS_get_asn1(key, &seed, CBS_ASN1_CONTEXT_SPECIFIC | 0)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } - } else if (CBS_len(key) == out->pkey.pqdsa_key->pqdsa->keygen_seed_len) { - if (!PQDSA_KEY_set_raw_keypair_from_seed(out->pkey.pqdsa_key, key)) { - // PQDSA_KEY_set_raw_keypair_from_seed sets the appropriate error. + if (CBS_len(&seed) != out->pkey.pqdsa_key->pqdsa->keygen_seed_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); return 0; } + + return PQDSA_KEY_set_raw_keypair_from_seed(out->pkey.pqdsa_key, &seed); + } else if (CBS_peek_asn1_tag(key, CBS_ASN1_OCTETSTRING)) { + // Case 2: expandedKey OCTET STRING + CBS expanded_key; + if (!CBS_get_asn1(key, &expanded_key, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (CBS_len(&expanded_key) != out->pkey.pqdsa_key->pqdsa->private_key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); + return 0; + } + + return PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key, &expanded_key); + } else { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; } - return 1; } static int pqdsa_priv_encode(CBB *out, const EVP_PKEY *pkey) { PQDSA_KEY *key = pkey->pkey.pqdsa_key; const PQDSA *pqdsa = key->pqdsa; - if (key->private_key == NULL) { + if (key->seed == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); return 0; } // See https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/ section 6. - CBB pkcs8, algorithm, oid, private_key; + CBB pkcs8, algorithm, oid, private_key, seed_choice; if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1_uint64(&pkcs8, PKCS8_VERSION_ONE /* version */) || !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || !CBB_add_bytes(&oid, pqdsa->oid, pqdsa->oid_len) || !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || - !CBB_add_bytes(&private_key, key->private_key, pqdsa->private_key_len) || + !CBB_add_asn1(&private_key, &seed_choice, CBS_ASN1_CONTEXT_SPECIFIC | 0) || + !CBB_add_bytes(&seed_choice, key->seed, pqdsa->keygen_seed_len) || !CBB_flush(out)) { OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; diff --git a/crypto/evp_extra/p_pqdsa_test.cc b/crypto/evp_extra/p_pqdsa_test.cc index 37c078620d..27a75d4de1 100644 --- a/crypto/evp_extra/p_pqdsa_test.cc +++ b/crypto/evp_extra/p_pqdsa_test.cc @@ -1089,20 +1089,20 @@ const char *mldsa_87_pub_pem_str = // C.1. Example Private Key const char *mldsa_44_priv_pem_str = "-----BEGIN PRIVATE KEY-----\n" -"MDICAQAwCwYJYIZIAWUDBAMRBCAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob\n" -"HB0eHw==\n" +"MDQCAQAwCwYJYIZIAWUDBAMRBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n" +"GhscHR4f\n" "-----END PRIVATE KEY-----\n"; const char *mldsa_65_priv_pem_str = "-----BEGIN PRIVATE KEY-----\n" -"MDICAQAwCwYJYIZIAWUDBAMSBCAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob\n" -"HB0eHw==\n" +"MDQCAQAwCwYJYIZIAWUDBAMSBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n" +"GhscHR4f\n" "-----END PRIVATE KEY-----\n"; const char *mldsa_87_priv_pem_str = "-----BEGIN PRIVATE KEY-----\n" -"MDICAQAwCwYJYIZIAWUDBAMTBCAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRob\n" -"HB0eHw==\n" +"MDQCAQAwCwYJYIZIAWUDBAMTBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n" +"GhscHR4f\n" "-----END PRIVATE KEY-----\n"; struct PQDSATestVector { @@ -1463,11 +1463,10 @@ TEST_P(PQDSAParameterTest, RawFunctions) { EXPECT_NE(private_pkey->pkey.pqdsa_key->private_key, nullptr); // ---- 5. Test get_raw public/private failure modes ---- - uint8_t *buf = nullptr; - size_t buf_size; + std::vector get_sk(sk_len); // Attempting to get a private key that is not present must fail correctly - EXPECT_FALSE(EVP_PKEY_get_raw_private_key(public_pkey.get(), buf, &buf_size)); + EXPECT_FALSE(EVP_PKEY_get_raw_private_key(public_pkey.get(), get_sk.data(), &sk_len)); GET_ERR_AND_CHECK_REASON(EVP_R_NOT_A_PRIVATE_KEY); // Null PKEY must fail correctly. @@ -1754,6 +1753,15 @@ TEST_P(PQDSAParameterTest, ParsePrivateKey) { // the public key that was parsed from PEM. ASSERT_EQ(1, EVP_PKEY_cmp(pkey1.get(), pkey2.get())); + // ---- 5. test failure modes ---- + // Test case in which a parsed key does not contain a seed + bssl::ScopedCBB cbb; + void *tmp = (void*) pkey1.get()->pkey.pqdsa_key->seed; + pkey1.get()->pkey.pqdsa_key->seed =nullptr; + ASSERT_TRUE(CBB_init(cbb.get(), 0)); + ASSERT_FALSE(EVP_marshal_private_key(cbb.get(), pkey1.get())); + pkey1.get()->pkey.pqdsa_key->seed = (uint8_t *)tmp; + // Clean up OPENSSL_free(der_pub); OPENSSL_free(der_priv); @@ -1780,7 +1788,7 @@ TEST_P(PQDSAParameterTest, KeyConsistencyTest) { // ---- 3. Generate a raw public key from the raw private key ---- ASSERT_TRUE(GetParam().pack_key(pk.data(), sk.data())); - // ---- 4. Generate a raw public key from the raw private key ---- + // ---- 4. Test that the calculated pk is equal to original pkey ---- CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len); } diff --git a/crypto/evp_extra/p_rsa_asn1.c b/crypto/evp_extra/p_rsa_asn1.c index 05f5881112..3b53cf482f 100644 --- a/crypto/evp_extra/p_rsa_asn1.c +++ b/crypto/evp_extra/p_rsa_asn1.c @@ -85,7 +85,7 @@ static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int rsa_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // The IETF specification defines that the parameters must be // NULL. See RFC 3279, section 2.3.1. // There is also an ITU-T X.509 specification that is rarely seen, @@ -105,7 +105,7 @@ static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { return 1; } -static int rsa_pss_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int rsa_pss_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { RSASSA_PSS_PARAMS *pss = NULL; if (!RSASSA_PSS_parse_params(params, &pss)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); @@ -152,7 +152,7 @@ static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int rsa_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { if(pubkey) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; @@ -178,7 +178,7 @@ static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { return 1; } -static int rsa_pss_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int rsa_pss_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { RSASSA_PSS_PARAMS *pss = NULL; if (!RSASSA_PSS_parse_params(params, &pss)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); diff --git a/crypto/evp_extra/p_x25519_asn1.c b/crypto/evp_extra/p_x25519_asn1.c index b6963a8228..c9344963dc 100644 --- a/crypto/evp_extra/p_x25519_asn1.c +++ b/crypto/evp_extra/p_x25519_asn1.c @@ -121,7 +121,7 @@ static int x25519_get_pub_raw(const EVP_PKEY *pkey, uint8_t *out, return 1; } -static int x25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static int x25519_pub_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key) { // See RFC 8410, section 4. // The parameters must be omitted. Public keys have length 32. @@ -159,7 +159,7 @@ static int x25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { return OPENSSL_memcmp(a_key->pub, b_key->pub, 32) == 0; } -static int x25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) { +static int x25519_priv_decode(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey) { // See RFC 8410, section 7. // Parameters must be empty. The key is a 32-byte value wrapped in an extra diff --git a/crypto/fipsmodule/evp/internal.h b/crypto/fipsmodule/evp/internal.h index 3daa5e1bd3..9a4e14ca22 100644 --- a/crypto/fipsmodule/evp/internal.h +++ b/crypto/fipsmodule/evp/internal.h @@ -95,7 +95,7 @@ struct evp_pkey_asn1_method_st { // leading padding byte checked and removed. Although X.509 uses BIT STRINGs // to represent SubjectPublicKeyInfo, every key type defined encodes the key // as a byte string with the same conversion to BIT STRING. - int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); + int (*pub_decode)(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key); // pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result // to |out|. It returns one on success and zero on error. @@ -107,7 +107,7 @@ struct evp_pkey_asn1_method_st { // result into |out|. It returns one on success and zero on error. |params| is // the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| // is the contents of the OCTET STRING privateKey field. - int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey); + int (*priv_decode)(EVP_PKEY *out, CBS *oid, CBS *params, CBS *key, CBS *pubkey); // priv_encode encodes |key| as a PrivateKeyInfo and appends the result to // |out|. It returns one on success and zero on error. diff --git a/crypto/fipsmodule/evp/p_pqdsa.c b/crypto/fipsmodule/evp/p_pqdsa.c index 2e82df2aee..8cdf340586 100644 --- a/crypto/fipsmodule/evp/p_pqdsa.c +++ b/crypto/fipsmodule/evp/p_pqdsa.c @@ -49,7 +49,7 @@ static int pkey_pqdsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { PQDSA_KEY *key = PQDSA_KEY_new(); if (key == NULL || !PQDSA_KEY_init(key, pqdsa) || - !pqdsa->method->pqdsa_keygen(key->public_key, key->private_key) || + !pqdsa->method->pqdsa_keygen(key->public_key, key->private_key, key->seed) || !EVP_PKEY_assign(pkey, EVP_PKEY_PQDSA, key)) { PQDSA_KEY_free(key); return 0; diff --git a/crypto/fipsmodule/ml_dsa/ml_dsa.c b/crypto/fipsmodule/ml_dsa/ml_dsa.c index 512195658b..9fc6a86f1d 100644 --- a/crypto/fipsmodule/ml_dsa/ml_dsa.c +++ b/crypto/fipsmodule/ml_dsa/ml_dsa.c @@ -39,11 +39,12 @@ int ml_dsa_44_keypair_internal_no_self_test(uint8_t *public_key /* OUT */, } int ml_dsa_44_keypair(uint8_t *public_key /* OUT */, - uint8_t *private_key /* OUT */) { + uint8_t *private_key /* OUT */, + uint8_t *seed /* OUT */) { boringssl_ensure_ml_dsa_self_test(); ml_dsa_params params; ml_dsa_44_params_init(¶ms); - return (ml_dsa_keypair(¶ms, public_key, private_key) == 0); + return (ml_dsa_keypair(¶ms, public_key, private_key, seed) == 0); } int ml_dsa_44_pack_pk_from_sk(uint8_t *public_key /* OUT */, @@ -186,11 +187,12 @@ int ml_dsa_extmu_44_verify_internal(const uint8_t *public_key /* IN */, } int ml_dsa_65_keypair(uint8_t *public_key /* OUT */, - uint8_t *private_key /* OUT */) { + uint8_t *private_key /* OUT */, + uint8_t *seed /* OUT */) { boringssl_ensure_ml_dsa_self_test(); ml_dsa_params params; ml_dsa_65_params_init(¶ms); - return (ml_dsa_keypair(¶ms, public_key, private_key) == 0); + return (ml_dsa_keypair(¶ms, public_key, private_key, seed) == 0); } int ml_dsa_65_pack_pk_from_sk(uint8_t *public_key /* OUT */, @@ -318,11 +320,12 @@ int ml_dsa_extmu_65_verify_internal(const uint8_t *public_key /* IN */, } int ml_dsa_87_keypair(uint8_t *public_key /* OUT */, - uint8_t *private_key /* OUT */) { + uint8_t *private_key /* OUT */, + uint8_t *seed /* OUT */) { boringssl_ensure_ml_dsa_self_test(); ml_dsa_params params; ml_dsa_87_params_init(¶ms); - return (ml_dsa_keypair(¶ms, public_key, private_key) == 0); + return (ml_dsa_keypair(¶ms, public_key, private_key, seed) == 0); } int ml_dsa_87_pack_pk_from_sk(uint8_t *public_key /* OUT */, diff --git a/crypto/fipsmodule/ml_dsa/ml_dsa.h b/crypto/fipsmodule/ml_dsa/ml_dsa.h index 79f220cde2..0d4cbbd781 100644 --- a/crypto/fipsmodule/ml_dsa/ml_dsa.h +++ b/crypto/fipsmodule/ml_dsa/ml_dsa.h @@ -31,7 +31,8 @@ extern "C" { #endif OPENSSL_EXPORT int ml_dsa_44_keypair(uint8_t *public_key, - uint8_t *secret_key); + uint8_t *secret_key, + uint8_t *seed); OPENSSL_EXPORT int ml_dsa_44_pack_pk_from_sk(uint8_t *public_key, const uint8_t *private_key); @@ -96,7 +97,8 @@ OPENSSL_EXPORT int ml_dsa_extmu_44_verify_internal(const uint8_t *public_key, const uint8_t *pre, size_t pre_len); OPENSSL_EXPORT int ml_dsa_65_keypair(uint8_t *public_key, - uint8_t *secret_key); + uint8_t *secret_key, + uint8_t *seed); OPENSSL_EXPORT int ml_dsa_65_pack_pk_from_sk(uint8_t *public_key, const uint8_t *private_key); @@ -146,7 +148,8 @@ OPENSSL_EXPORT int ml_dsa_extmu_65_verify_internal(const uint8_t *public_key, const uint8_t *pre, size_t pre_len); OPENSSL_EXPORT int ml_dsa_87_keypair(uint8_t *public_key, - uint8_t *secret_key); + uint8_t *secret_key, + uint8_t *seed); OPENSSL_EXPORT int ml_dsa_87_pack_pk_from_sk(uint8_t *public_key, const uint8_t *private_key); diff --git a/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.c b/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.c index bfcc5e9bd3..6765f1594b 100644 --- a/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.c +++ b/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.c @@ -127,20 +127,20 @@ int ml_dsa_keypair_internal(ml_dsa_params *params, * Generates public and private key. * * Arguments: - ml_dsa_params: parameter struct -* - uint8_t *pk: pointer to output public key (allocated -* array of CRYPTO_PUBLICKEYBYTES bytes) -* - uint8_t *sk: pointer to output private key (allocated -* array of CRYPTO_SECRETKEYBYTES bytes) +* - uint8_t *pk: pointer to output public key (allocated +* array of CRYPTO_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key (allocated +* array of CRYPTO_SECRETKEYBYTES bytes) +* - uint8_t *seed: pointer to output keygen seed (allocated +* array of ML_DSA_SEEDBYTES bytes) * * Returns 0 (success) -1 on failure **************************************************/ -int ml_dsa_keypair(ml_dsa_params *params, uint8_t *pk, uint8_t *sk) { - uint8_t seed[ML_DSA_SEEDBYTES]; +int ml_dsa_keypair(ml_dsa_params *params, uint8_t *pk, uint8_t *sk, uint8_t *seed) { if (!RAND_bytes(seed, ML_DSA_SEEDBYTES)) { return -1; } int result = ml_dsa_keypair_internal(params, pk, sk, seed); - OPENSSL_cleanse(seed, sizeof(seed)); return result; } diff --git a/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.h b/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.h index 6f18bbab8a..43f02450a0 100644 --- a/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.h +++ b/crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.h @@ -5,7 +5,10 @@ #include #include "params.h" -int ml_dsa_keypair(ml_dsa_params *params, uint8_t *pk, uint8_t *sk); +int ml_dsa_keypair(ml_dsa_params *params, + uint8_t *pk, + uint8_t *sk, + uint8_t *seed); int ml_dsa_keypair_internal(ml_dsa_params *params, uint8_t *pk, diff --git a/crypto/fipsmodule/pqdsa/internal.h b/crypto/fipsmodule/pqdsa/internal.h index 390489a8f0..d6432079a3 100644 --- a/crypto/fipsmodule/pqdsa/internal.h +++ b/crypto/fipsmodule/pqdsa/internal.h @@ -13,7 +13,8 @@ extern "C" { // PQDSA_METHOD structure and helper functions. typedef struct { int (*pqdsa_keygen)(uint8_t *public_key, - uint8_t *private_key); + uint8_t *private_key, + uint8_t *keygen_seed); int (*pqdsa_keygen_internal)(uint8_t *public_key, uint8_t *private_key, @@ -70,6 +71,7 @@ struct pqdsa_key_st { const PQDSA *pqdsa; uint8_t *public_key; uint8_t *private_key; + uint8_t *seed; }; int PQDSA_KEY_init(PQDSA_KEY *key, const PQDSA *pqdsa); diff --git a/crypto/fipsmodule/pqdsa/pqdsa.c b/crypto/fipsmodule/pqdsa/pqdsa.c index 258659ecb4..b5fa707a42 100644 --- a/crypto/fipsmodule/pqdsa/pqdsa.c +++ b/crypto/fipsmodule/pqdsa/pqdsa.c @@ -34,8 +34,10 @@ static void PQDSA_KEY_clear(PQDSA_KEY *key) { key->pqdsa = NULL; OPENSSL_free(key->public_key); OPENSSL_free(key->private_key); + OPENSSL_free(key->seed); key->public_key = NULL; key->private_key = NULL; + key->seed = NULL; } int PQDSA_KEY_init(PQDSA_KEY *key, const PQDSA *pqdsa) { @@ -48,7 +50,8 @@ int PQDSA_KEY_init(PQDSA_KEY *key, const PQDSA *pqdsa) { key->pqdsa = pqdsa; key->public_key = OPENSSL_malloc(pqdsa->public_key_len); key->private_key = OPENSSL_malloc(pqdsa->private_key_len); - if (key->public_key == NULL || key->private_key == NULL) { + key->seed = OPENSSL_malloc(pqdsa->keygen_seed_len); + if (key->public_key == NULL || key->private_key == NULL || key->seed == NULL) { PQDSA_KEY_clear(key); return 0; } @@ -101,18 +104,37 @@ int PQDSA_KEY_set_raw_keypair_from_seed(PQDSA_KEY *key, CBS *in) { return 0; } + uint8_t *seed = OPENSSL_malloc(key->pqdsa->keygen_seed_len); + if (seed == NULL) { + OPENSSL_free(private_key); + OPENSSL_free(public_key); + return 0; + } + // attempt to generate the key from the provided seed if (!key->pqdsa->method->pqdsa_keygen_internal(public_key, private_key, CBS_data(in))) { + OPENSSL_free(public_key); + OPENSSL_free(private_key); + OPENSSL_free(seed); OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } - // set the public and private key + // copy the seed data + if (!CBS_copy_bytes(in, seed, key->pqdsa->keygen_seed_len)) { + OPENSSL_free(public_key); + OPENSSL_free(private_key); + OPENSSL_free(seed); + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + // set the public key, private key, and seed key->public_key = public_key; key->private_key = private_key; - + key->seed = seed; return 1; } diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 558dfb8051..4ddd3a167f 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -249,7 +249,7 @@ OPENSSL_EXPORT EVP_PKEY *EVP_parse_private_key(CBS *cbs); // EVP_marshal_private_key marshals |key| as a DER-encoded PrivateKeyInfo // structure (RFC 5208) and appends the result to |cbb|. It returns one on -// success and zero on error. +// success and zero on error. For ML-DSA, the private seed is encoded. OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key); // EVP_marshal_private_key_v2 marshals |key| as a DER-encoded